mirror of
https://github.com/doocs/md.git
synced 2024-11-24 19:10:34 +08:00
style: Unified repository code style (#135)
This commit is contained in:
parent
e23b354006
commit
6202ad2ff0
1
.gitignore
vendored
1
.gitignore
vendored
@ -17,7 +17,6 @@
|
|||||||
.env.development.local
|
.env.development.local
|
||||||
.env.test.local
|
.env.test.local
|
||||||
.env.production.local
|
.env.production.local
|
||||||
.vscode
|
|
||||||
|
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
|
4
.husky/pre-commit
Normal file
4
.husky/pre-commit
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
npm run lint
|
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.fixAll": true
|
||||||
|
}
|
||||||
|
}
|
9
jsconfig.json
Normal file
9
jsconfig.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "./",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["src/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"exclude": ["node_modules", "dist"]
|
||||||
|
}
|
@ -10,11 +10,11 @@ const spaceInfo = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置说明请参考文档:
|
* 配置说明请参考文档:
|
||||||
* https://hongqiye.com/doc/mockm/config/option.html
|
* https://hongqiye.com/doc/mockm/config/option.html
|
||||||
* @type {import('mockm/@types/config').Config}
|
* @type {import('mockm/@types/config').Config}
|
||||||
*/
|
*/
|
||||||
module.exports = util => {
|
module.exports = (util) => {
|
||||||
const port = 9000
|
const port = 9000
|
||||||
return {
|
return {
|
||||||
port,
|
port,
|
||||||
@ -29,26 +29,34 @@ module.exports = util => {
|
|||||||
})
|
})
|
||||||
form.parse(req, async (err, fields = [], files) => {
|
form.parse(req, async (err, fields = [], files) => {
|
||||||
const file = files.file[0]
|
const file = files.file[0]
|
||||||
let url = `http://127.0.0.1:${port}/public/upload/${path.parse(file.path).base}`
|
let url = `http://127.0.0.1:${port}/public/upload/${
|
||||||
|
path.parse(file.path).base
|
||||||
|
}`
|
||||||
try {
|
try {
|
||||||
url = await dcloud(spaceInfo)({name: file.originalFilename, file: fs.createReadStream(file.path)})
|
url = await dcloud(spaceInfo)({
|
||||||
|
name: file.originalFilename,
|
||||||
|
file: fs.createReadStream(file.path),
|
||||||
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// console.log(err)
|
// console.log(err)
|
||||||
}
|
}
|
||||||
res.json({url})
|
res.json({ url })
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
static: [
|
static: [
|
||||||
{ // 测试 netlify 部署
|
{
|
||||||
|
// 测试 netlify 部署
|
||||||
fileDir: `../dist`,
|
fileDir: `../dist`,
|
||||||
path: `/`,
|
path: `/`,
|
||||||
},
|
},
|
||||||
{ // 测试 gitee/github 部署
|
{
|
||||||
|
// 测试 gitee/github 部署
|
||||||
fileDir: `../dist`,
|
fileDir: `../dist`,
|
||||||
path: `/md`,
|
path: `/md`,
|
||||||
},
|
},
|
||||||
{ // 访问公共目录
|
{
|
||||||
|
// 访问公共目录
|
||||||
fileDir: `../public`,
|
fileDir: `../public`,
|
||||||
path: `/public`,
|
path: `/public`,
|
||||||
},
|
},
|
||||||
|
27
mm/util.js
27
mm/util.js
@ -1,19 +1,23 @@
|
|||||||
const fetch = (...args) => import(`node-fetch`).then(({default: fetch}) => fetch(...args))
|
const fetch = (...args) =>
|
||||||
|
import(`node-fetch`).then(({ default: fetch }) => fetch(...args))
|
||||||
const FormData = require(`form-data`)
|
const FormData = require(`form-data`)
|
||||||
|
|
||||||
function dcloud(spaceInfo) {
|
function dcloud(spaceInfo) {
|
||||||
if(Boolean(spaceInfo.spaceId && spaceInfo.clientSecret) === false) {
|
if (Boolean(spaceInfo.spaceId && spaceInfo.clientSecret) === false) {
|
||||||
throw new Error(`请填写 spaceInfo`)
|
throw new Error(`请填写 spaceInfo`)
|
||||||
}
|
}
|
||||||
|
|
||||||
function sign(data, secret) {
|
function sign(data, secret) {
|
||||||
const hmac = require(`crypto`).createHmac(`md5`, secret)
|
const hmac = require(`crypto`).createHmac(`md5`, secret)
|
||||||
// 排序 obj 再转换为 key=val&key=val 的格式
|
// 排序 obj 再转换为 key=val&key=val 的格式
|
||||||
const str = Object.keys(data).sort().reduce((acc, cur) => `${acc}&${cur}=${data[cur]}`, ``).slice(1)
|
const str = Object.keys(data)
|
||||||
|
.sort()
|
||||||
|
.reduce((acc, cur) => `${acc}&${cur}=${data[cur]}`, ``)
|
||||||
|
.slice(1)
|
||||||
hmac.update(str)
|
hmac.update(str)
|
||||||
return hmac.digest(`hex`)
|
return hmac.digest(`hex`)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function anonymousAuthorize() {
|
async function anonymousAuthorize() {
|
||||||
const data = {
|
const data = {
|
||||||
method: `serverless.auth.user.anonymousAuthorize`,
|
method: `serverless.auth.user.anonymousAuthorize`,
|
||||||
@ -29,7 +33,7 @@ function dcloud(spaceInfo) {
|
|||||||
method: `POST`,
|
method: `POST`,
|
||||||
}).then((res) => res.json())
|
}).then((res) => res.json())
|
||||||
}
|
}
|
||||||
|
|
||||||
async function report({ id, token }) {
|
async function report({ id, token }) {
|
||||||
const reportReq = {
|
const reportReq = {
|
||||||
method: `serverless.file.resource.report`,
|
method: `serverless.file.resource.report`,
|
||||||
@ -47,7 +51,7 @@ function dcloud(spaceInfo) {
|
|||||||
method: `POST`,
|
method: `POST`,
|
||||||
}).then((res) => res.json())
|
}).then((res) => res.json())
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generateProximalSign({ name, token }) {
|
async function generateProximalSign({ name, token }) {
|
||||||
const data = {
|
const data = {
|
||||||
method: `serverless.file.resource.generateProximalSign`,
|
method: `serverless.file.resource.generateProximalSign`,
|
||||||
@ -66,7 +70,7 @@ function dcloud(spaceInfo) {
|
|||||||
}).then((res) => res.json())
|
}).then((res) => res.json())
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
async function upload({ data, file }) {
|
async function upload({ data, file }) {
|
||||||
const formdata = new FormData()
|
const formdata = new FormData()
|
||||||
Object.entries({
|
Object.entries({
|
||||||
@ -81,7 +85,7 @@ function dcloud(spaceInfo) {
|
|||||||
success_action_status: 200,
|
success_action_status: 200,
|
||||||
file,
|
file,
|
||||||
}).forEach(([key, val]) => formdata.append(key, val))
|
}).forEach(([key, val]) => formdata.append(key, val))
|
||||||
|
|
||||||
return await fetch(`https://${data.host}`, {
|
return await fetch(`https://${data.host}`, {
|
||||||
headers: {
|
headers: {
|
||||||
'X-OSS-server-side-encrpytion': `AES256`,
|
'X-OSS-server-side-encrpytion': `AES256`,
|
||||||
@ -90,7 +94,7 @@ function dcloud(spaceInfo) {
|
|||||||
method: `POST`,
|
method: `POST`,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function uploadFile({ name = `unnamed.file`, file }) {
|
async function uploadFile({ name = `unnamed.file`, file }) {
|
||||||
const token = (await anonymousAuthorize()).data.accessToken
|
const token = (await anonymousAuthorize()).data.accessToken
|
||||||
const res = await generateProximalSign({ name, token })
|
const res = await generateProximalSign({ name, token })
|
||||||
@ -99,9 +103,8 @@ function dcloud(spaceInfo) {
|
|||||||
const fileUrl = `https://${res.data.cdnDomain}/${res.data.ossPath}`
|
const fileUrl = `https://${res.data.cdnDomain}/${res.data.ossPath}`
|
||||||
return fileUrl
|
return fileUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
return uploadFile
|
return uploadFile
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
48
package.json
48
package.json
@ -3,6 +3,8 @@
|
|||||||
"version": "1.5.7",
|
"version": "1.5.7",
|
||||||
"private": false,
|
"private": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"prepare": "husky install",
|
||||||
|
"lint": "vue-cli-service lint src && vue-cli-service lint mm",
|
||||||
"start": "run-p serve mm",
|
"start": "run-p serve mm",
|
||||||
"serve": "vue-cli-service serve",
|
"serve": "vue-cli-service serve",
|
||||||
"build:h5-netlify": "cross-env SERVER_ENV=NETLIFY vue-cli-service build",
|
"build:h5-netlify": "cross-env SERVER_ENV=NETLIFY vue-cli-service build",
|
||||||
@ -10,6 +12,43 @@
|
|||||||
"build-cli": "npm run build && npx shx rm -rf md-cli/dist && npx shx rm -rf dist/**/*.map && npx shx cp -r dist md-cli/ && cd md-cli && npm pack",
|
"build-cli": "npm run build && npx shx rm -rf md-cli/dist && npx shx rm -rf dist/**/*.map && npx shx cp -r dist md-cli/ && cd md-cli && npm pack",
|
||||||
"mm": "npx mockm --cwd=mm"
|
"mm": "npx mockm --cwd=mm"
|
||||||
},
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"root": true,
|
||||||
|
"env": {
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"plugin:vue/essential",
|
||||||
|
"eslint:recommended",
|
||||||
|
"@vue/prettier"
|
||||||
|
],
|
||||||
|
"parserOptions": {
|
||||||
|
"parser": "babel-eslint"
|
||||||
|
},
|
||||||
|
"ignorePatterns": [
|
||||||
|
"src/assets/scripts/renderers"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"prettier/prettier": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"singleQuote": true,
|
||||||
|
"semi": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"semi": [
|
||||||
|
"error",
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
"quotes": [
|
||||||
|
"error",
|
||||||
|
"backtick"
|
||||||
|
],
|
||||||
|
"no-unused-vars": "off",
|
||||||
|
"no-console": "off",
|
||||||
|
"no-debugger": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/shared": "^3.2.26",
|
"@vue/shared": "^3.2.26",
|
||||||
"ali-oss": "^6.16.0",
|
"ali-oss": "^6.16.0",
|
||||||
@ -37,6 +76,15 @@
|
|||||||
"vuex": "^3.6.2"
|
"vuex": "^3.6.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@vue/cli-plugin-eslint": "^4.5.12",
|
||||||
|
"@vue/cli-plugin-router": "^4.5.12",
|
||||||
|
"@vue/cli-plugin-vuex": "^4.5.12",
|
||||||
|
"@vue/eslint-config-prettier": "^6.0.0",
|
||||||
|
"babel-eslint": "^10.1.0",
|
||||||
|
"eslint": "^6.8.0",
|
||||||
|
"eslint-plugin-prettier": "^3.4.0",
|
||||||
|
"eslint-plugin-vue": "^6.2.2",
|
||||||
|
"husky": "^7.0.4",
|
||||||
"@vue/cli-plugin-babel": "~4.5.15",
|
"@vue/cli-plugin-babel": "~4.5.15",
|
||||||
"@vue/cli-service": "~4.5.15",
|
"@vue/cli-service": "~4.5.15",
|
||||||
"async-validator": "^4.0.7",
|
"async-validator": "^4.0.7",
|
||||||
|
@ -18,8 +18,8 @@ body,
|
|||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
/* 每个页面公共css */
|
/* 每个页面公共css */
|
||||||
@import url("./assets/less/style-mirror.css");
|
@import url('./assets/less/style-mirror.css');
|
||||||
@import url("./assets/less/theme.less");
|
@import url('./assets/less/theme.less');
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 6px;
|
width: 6px;
|
||||||
|
@ -1,55 +1,55 @@
|
|||||||
const githubConfig = {
|
const githubConfig = {
|
||||||
username: "filess",
|
username: `filess`,
|
||||||
repoList: Array.from(
|
repoList: Array.from(
|
||||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
|
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
|
||||||
(e) => `img${e}`
|
(e) => `img${e}`
|
||||||
),
|
),
|
||||||
branch: "main",
|
branch: `main`,
|
||||||
accessTokenList: [
|
accessTokenList: [
|
||||||
"7715d7ca67b5d3837cfdoocsmde8c38421815aa423510af",
|
`7715d7ca67b5d3837cfdoocsmde8c38421815aa423510af`,
|
||||||
"c411415bf95dbe39625doocsmd5047ba9b7a2a6c9642abe",
|
`c411415bf95dbe39625doocsmd5047ba9b7a2a6c9642abe`,
|
||||||
"2821cd8819fa345c053doocsmdca86ac653f8bc20db1f1b",
|
`2821cd8819fa345c053doocsmdca86ac653f8bc20db1f1b`,
|
||||||
"445f0dae46ef1f2a4d6doocsmdc797301e94797b4750a4c",
|
`445f0dae46ef1f2a4d6doocsmdc797301e94797b4750a4c`,
|
||||||
"cc1d0c1426d0fd0902bdoocsmdd2d7184b14da61b86ec46",
|
`cc1d0c1426d0fd0902bdoocsmdd2d7184b14da61b86ec46`,
|
||||||
"b67e9d15cb6f910492fdoocsmdac6b44d379c953bb19eff",
|
`b67e9d15cb6f910492fdoocsmdac6b44d379c953bb19eff`,
|
||||||
"618c4dc2244ccbbc088doocsmd125d17fd31b7d06a50cf3",
|
`618c4dc2244ccbbc088doocsmd125d17fd31b7d06a50cf3`,
|
||||||
"a4b581732e1c1507458doocsmdc5b223b27dae5e2e16a55",
|
`a4b581732e1c1507458doocsmdc5b223b27dae5e2e16a55`,
|
||||||
"77904db41aee57ad79bdoocsmd760f848201dac9c96fd5e",
|
`77904db41aee57ad79bdoocsmd760f848201dac9c96fd5e`,
|
||||||
"02f251cb14ac62ab100doocsmdddbfc8527d773f1f04ce1",
|
`02f251cb14ac62ab100doocsmdddbfc8527d773f1f04ce1`,
|
||||||
"eb321079a95ba7028d9doocsmde2e84c502dac70de7cf08",
|
`eb321079a95ba7028d9doocsmde2e84c502dac70de7cf08`,
|
||||||
"22f74fcfb071a961fa2doocsmde28dabc746f0503a15e5d",
|
`22f74fcfb071a961fa2doocsmde28dabc746f0503a15e5d`,
|
||||||
"85124c2bfe7abba0938doocsmd0af7f67918b99d085a5fd",
|
`85124c2bfe7abba0938doocsmd0af7f67918b99d085a5fd`,
|
||||||
"0a561b4d4bbecb2de7edoocsmdd9ba3833d11dbc5e430f5",
|
`0a561b4d4bbecb2de7edoocsmdd9ba3833d11dbc5e430f5`,
|
||||||
"e8a01491188d8d5a097doocsmd03ede0aad1fe9e3af24e9",
|
`e8a01491188d8d5a097doocsmd03ede0aad1fe9e3af24e9`,
|
||||||
"36e1f420d7e5bdebd67doocsmd65463562f5f25b20b8377",
|
`36e1f420d7e5bdebd67doocsmd65463562f5f25b20b8377`,
|
||||||
],
|
],
|
||||||
};
|
}
|
||||||
|
|
||||||
const giteeConfig = {
|
const giteeConfig = {
|
||||||
username: "filesss",
|
username: `filesss`,
|
||||||
repoList: Array.from(
|
repoList: Array.from(
|
||||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
|
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
|
||||||
(e) => `img${e}`
|
(e) => `img${e}`
|
||||||
),
|
),
|
||||||
branch: "main",
|
branch: `main`,
|
||||||
accessTokenList: [
|
accessTokenList: [
|
||||||
"ed5fc9866bd6c2fdoocsmddd433f806fd2f399c",
|
`ed5fc9866bd6c2fdoocsmddd433f806fd2f399c`,
|
||||||
"5448ffebbbf1151doocsmdc4e337cf814fc8a62",
|
`5448ffebbbf1151doocsmdc4e337cf814fc8a62`,
|
||||||
"25b05efd2557ca2doocsmd75b5c0835e3395911",
|
`25b05efd2557ca2doocsmd75b5c0835e3395911`,
|
||||||
"11628c7a5aef015doocsmd2eeff9fb9566f0458",
|
`11628c7a5aef015doocsmd2eeff9fb9566f0458`,
|
||||||
"cb2f5145ed938dedoocsmdbd063b4ed244eecf8",
|
`cb2f5145ed938dedoocsmdbd063b4ed244eecf8`,
|
||||||
"d8c0b57500672c1doocsmd55f48b866b5ebcd98",
|
`d8c0b57500672c1doocsmd55f48b866b5ebcd98`,
|
||||||
"78c56eadb88e453doocsmd43ddd95753351771a",
|
`78c56eadb88e453doocsmd43ddd95753351771a`,
|
||||||
"03e1a688003948fdoocsmda16fcf41e6f03f1f0",
|
`03e1a688003948fdoocsmda16fcf41e6f03f1f0`,
|
||||||
"c49121cf4d191fbdoocsmdd6a7877ed537e474a",
|
`c49121cf4d191fbdoocsmdd6a7877ed537e474a`,
|
||||||
"adfeb2fadcdc4aadoocsmdfe1ee869ac9c968ff",
|
`adfeb2fadcdc4aadoocsmdfe1ee869ac9c968ff`,
|
||||||
"116c94549ca4a0ddoocsmd192653af5c0694616",
|
`116c94549ca4a0ddoocsmd192653af5c0694616`,
|
||||||
"ecf30ed7f2eb184doocsmd51ea4ec8300371d9e",
|
`ecf30ed7f2eb184doocsmd51ea4ec8300371d9e`,
|
||||||
"5837cf2bd5afd93doocsmd73904bed31934949e",
|
`5837cf2bd5afd93doocsmd73904bed31934949e`,
|
||||||
"b5b7e1c7d57e01fdoocsmd5266f552574297d78",
|
`b5b7e1c7d57e01fdoocsmd5266f552574297d78`,
|
||||||
"684d55564ffbd0bdoocsmd7d747e5cc23aed6d6",
|
`684d55564ffbd0bdoocsmd7d747e5cc23aed6d6`,
|
||||||
"3fc04a9d272ab71doocsmd010c56cb57d88d2ba",
|
`3fc04a9d272ab71doocsmd010c56cb57d88d2ba`,
|
||||||
],
|
],
|
||||||
};
|
}
|
||||||
|
|
||||||
export { githubConfig, giteeConfig };
|
export { githubConfig, giteeConfig }
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
import axios from "axios";
|
import axios from 'axios'
|
||||||
|
|
||||||
// 创建axios实例
|
// 创建axios实例
|
||||||
const service = axios.create({
|
const service = axios.create({
|
||||||
baseURL: "",
|
baseURL: ``,
|
||||||
timeout: 30 * 1000, // 请求超时时间
|
timeout: 30 * 1000, // 请求超时时间
|
||||||
});
|
})
|
||||||
|
|
||||||
service.interceptors.request.use(
|
service.interceptors.request.use(
|
||||||
(config) => {
|
(config) => {
|
||||||
if (/^(post)|(put)|(delete)$/i.test(config.method)) {
|
if (/^(post)|(put)|(delete)$/i.test(config.method)) {
|
||||||
if (config.data && config.data.upload) {
|
if (config.data && config.data.upload) {
|
||||||
config.headers["Content-Type"] = "multipart/form-data";
|
config.headers[`Content-Type`] = `multipart/form-data`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return config;
|
return config
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
Promise.reject(error);
|
Promise.reject(error)
|
||||||
}
|
}
|
||||||
);
|
)
|
||||||
|
|
||||||
service.interceptors.response.use(
|
service.interceptors.response.use(
|
||||||
(res) => {
|
(res) => {
|
||||||
return res.data ? res.data : Promise.reject(res);
|
return res.data ? res.data : Promise.reject(res)
|
||||||
},
|
},
|
||||||
(error) => Promise.reject(error)
|
(error) => Promise.reject(error)
|
||||||
);
|
)
|
||||||
|
|
||||||
export default service;
|
export default service
|
||||||
|
265
src/api/file.js
265
src/api/file.js
@ -1,47 +1,47 @@
|
|||||||
import fetch from "./fetch";
|
import fetch from './fetch'
|
||||||
import { githubConfig, giteeConfig } from "./config";
|
import { githubConfig, giteeConfig } from './config'
|
||||||
import CryptoJS from "crypto-js";
|
import CryptoJS from 'crypto-js'
|
||||||
import OSS from "ali-oss";
|
import OSS from 'ali-oss'
|
||||||
import * as Minio from "minio";
|
import * as Minio from 'minio'
|
||||||
import COS from "cos-js-sdk-v5";
|
import COS from 'cos-js-sdk-v5'
|
||||||
import Buffer from "buffer-from";
|
import Buffer from 'buffer-from'
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import * as qiniu from "qiniu-js";
|
import * as qiniu from 'qiniu-js'
|
||||||
import { utf16to8, base64encode, safe64 } from "../assets/scripts/tokenTools";
|
import { utf16to8, base64encode, safe64 } from '../assets/scripts/tokenTools'
|
||||||
import * as tokenTools from "../assets/scripts/tokenTools";
|
import * as tokenTools from '../assets/scripts/tokenTools'
|
||||||
|
|
||||||
function getConfig(useDefault, platform) {
|
function getConfig(useDefault, platform) {
|
||||||
if (useDefault) {
|
if (useDefault) {
|
||||||
// load default config file
|
// load default config file
|
||||||
const config = platform === "github" ? githubConfig : giteeConfig;
|
const config = platform === `github` ? githubConfig : giteeConfig
|
||||||
const { username, repoList, branch, accessTokenList } = config;
|
const { username, repoList, branch, accessTokenList } = config
|
||||||
|
|
||||||
// choose random token from access_token list
|
// choose random token from access_token list
|
||||||
const tokenIndex = Math.floor(Math.random() * accessTokenList.length);
|
const tokenIndex = Math.floor(Math.random() * accessTokenList.length)
|
||||||
const accessToken = accessTokenList[tokenIndex].replace("doocsmd", "");
|
const accessToken = accessTokenList[tokenIndex].replace(`doocsmd`, ``)
|
||||||
|
|
||||||
// choose random repo from repo list
|
// choose random repo from repo list
|
||||||
const repoIndex = Math.floor(Math.random() * repoList.length);
|
const repoIndex = Math.floor(Math.random() * repoList.length)
|
||||||
const repo = repoList[repoIndex];
|
const repo = repoList[repoIndex]
|
||||||
|
|
||||||
return { username, repo, branch, accessToken };
|
return { username, repo, branch, accessToken }
|
||||||
}
|
}
|
||||||
|
|
||||||
// load configuration from localStorage
|
// load configuration from localStorage
|
||||||
const customConfig = JSON.parse(localStorage.getItem(`${platform}Config`));
|
const customConfig = JSON.parse(localStorage.getItem(`${platform}Config`))
|
||||||
|
|
||||||
// split username/repo
|
// split username/repo
|
||||||
const repoUrl = customConfig.repo
|
const repoUrl = customConfig.repo
|
||||||
.replace(`https://${platform}.com/`, "")
|
.replace(`https://${platform}.com/`, ``)
|
||||||
.replace(`http://${platform}.com/`, "")
|
.replace(`http://${platform}.com/`, ``)
|
||||||
.replace(`${platform}.com/`, "")
|
.replace(`${platform}.com/`, ``)
|
||||||
.split("/");
|
.split(`/`)
|
||||||
return {
|
return {
|
||||||
username: repoUrl[0],
|
username: repoUrl[0],
|
||||||
repo: repoUrl[1],
|
repo: repoUrl[1],
|
||||||
branch: customConfig.branch || "master",
|
branch: customConfig.branch || `master`,
|
||||||
accessToken: customConfig.accessToken,
|
accessToken: customConfig.accessToken,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,11 +49,11 @@ function getConfig(useDefault, platform) {
|
|||||||
* @returns string
|
* @returns string
|
||||||
*/
|
*/
|
||||||
function getDir() {
|
function getDir() {
|
||||||
const date = new Date();
|
const date = new Date()
|
||||||
const year = date.getFullYear();
|
const year = date.getFullYear()
|
||||||
const month = (date.getMonth() + 1).toString().padStart(2, "0");
|
const month = (date.getMonth() + 1).toString().padStart(2, `0`)
|
||||||
const day = date.getDate().toString().padStart(2, "0");
|
const day = date.getDate().toString().padStart(2, `0`)
|
||||||
return `${year}/${month}/${day}`;
|
return `${year}/${month}/${day}`
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,9 +62,9 @@ function getDir() {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
function getDateFilename(filename) {
|
function getDateFilename(filename) {
|
||||||
const currentTimestamp = new Date().getTime();
|
const currentTimestamp = new Date().getTime()
|
||||||
const fileSuffix = filename.split(".")[1];
|
const fileSuffix = filename.split(`.`)[1]
|
||||||
return `${currentTimestamp}-${uuidv4()}.${fileSuffix}`;
|
return `${currentTimestamp}-${uuidv4()}.${fileSuffix}`
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
@ -72,17 +72,17 @@ function getDateFilename(filename) {
|
|||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
async function ghFileUpload(content, filename) {
|
async function ghFileUpload(content, filename) {
|
||||||
const useDefault = localStorage.getItem("imgHost") === "default";
|
const useDefault = localStorage.getItem(`imgHost`) === `default`
|
||||||
const { username, repo, branch, accessToken } = getConfig(
|
const { username, repo, branch, accessToken } = getConfig(
|
||||||
useDefault,
|
useDefault,
|
||||||
"github"
|
`github`
|
||||||
);
|
)
|
||||||
const dir = getDir();
|
const dir = getDir()
|
||||||
const url = `https://api.github.com/repos/${username}/${repo}/contents/${dir}/`;
|
const url = `https://api.github.com/repos/${username}/${repo}/contents/${dir}/`
|
||||||
const dateFilename = getDateFilename(filename);
|
const dateFilename = getDateFilename(filename)
|
||||||
const res = await fetch({
|
const res = await fetch({
|
||||||
url: url + dateFilename,
|
url: url + dateFilename,
|
||||||
method: "put",
|
method: `put`,
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `token ${accessToken}`,
|
Authorization: `token ${accessToken}`,
|
||||||
},
|
},
|
||||||
@ -91,13 +91,13 @@ async function ghFileUpload(content, filename) {
|
|||||||
branch,
|
branch,
|
||||||
message: `Upload by ${window.location.href}`,
|
message: `Upload by ${window.location.href}`,
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
const githubResourceUrl = `raw.githubusercontent.com/${username}/${repo}/${branch}/`;
|
const githubResourceUrl = `raw.githubusercontent.com/${username}/${repo}/${branch}/`
|
||||||
const cdnResourceUrl = `cdn.jsdelivr.net/gh/${username}/${repo}@${branch}/`;
|
const cdnResourceUrl = `cdn.jsdelivr.net/gh/${username}/${repo}@${branch}/`
|
||||||
res.content = res.data?.content || res.content;
|
res.content = res.data?.content || res.content
|
||||||
return useDefault
|
return useDefault
|
||||||
? res.content.download_url.replace(githubResourceUrl, cdnResourceUrl)
|
? res.content.download_url.replace(githubResourceUrl, cdnResourceUrl)
|
||||||
: res.content.download_url;
|
: res.content.download_url
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
@ -105,26 +105,23 @@ async function ghFileUpload(content, filename) {
|
|||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
async function giteeUpload(content, filename) {
|
async function giteeUpload(content, filename) {
|
||||||
const useDefault = localStorage.getItem("imgHost") === "default";
|
const useDefault = localStorage.getItem(`imgHost`) === `default`
|
||||||
const { username, repo, branch, accessToken } = getConfig(
|
const { username, repo, branch, accessToken } = getConfig(useDefault, `gitee`)
|
||||||
useDefault,
|
const dir = getDir()
|
||||||
"gitee"
|
const dateFilename = getDateFilename(filename)
|
||||||
);
|
const url = `https://gitee.com/api/v5/repos/${username}/${repo}/contents/${dir}/${dateFilename}`
|
||||||
const dir = getDir();
|
|
||||||
const dateFilename = getDateFilename(filename);
|
|
||||||
const url = `https://gitee.com/api/v5/repos/${username}/${repo}/contents/${dir}/${dateFilename}`;
|
|
||||||
const res = await fetch({
|
const res = await fetch({
|
||||||
url,
|
url,
|
||||||
method: "POST",
|
method: `POST`,
|
||||||
data: {
|
data: {
|
||||||
content,
|
content,
|
||||||
branch,
|
branch,
|
||||||
access_token: accessToken,
|
access_token: accessToken,
|
||||||
message: `Upload by ${window.location.href}`,
|
message: `Upload by ${window.location.href}`,
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
res.content = res.data?.content || res.content;
|
res.content = res.data?.content || res.content
|
||||||
return encodeURI(res.content.download_url);
|
return encodeURI(res.content.download_url)
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
@ -132,37 +129,37 @@ async function giteeUpload(content, filename) {
|
|||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
function getQiniuToken(accessKey, secretKey, putPolicy) {
|
function getQiniuToken(accessKey, secretKey, putPolicy) {
|
||||||
const policy = JSON.stringify(putPolicy);
|
const policy = JSON.stringify(putPolicy)
|
||||||
const encoded = base64encode(utf16to8(policy));
|
const encoded = base64encode(utf16to8(policy))
|
||||||
const hash = CryptoJS.HmacSHA1(encoded, secretKey);
|
const hash = CryptoJS.HmacSHA1(encoded, secretKey)
|
||||||
const encodedSigned = hash.toString(CryptoJS.enc.Base64);
|
const encodedSigned = hash.toString(CryptoJS.enc.Base64)
|
||||||
return `${accessKey}:${safe64(encodedSigned)}:${encoded}`;
|
return `${accessKey}:${safe64(encodedSigned)}:${encoded}`
|
||||||
}
|
}
|
||||||
|
|
||||||
async function qiniuUpload(file) {
|
async function qiniuUpload(file) {
|
||||||
const { accessKey, secretKey, bucket, region, path, domain } = JSON.parse(
|
const { accessKey, secretKey, bucket, region, path, domain } = JSON.parse(
|
||||||
localStorage.getItem("qiniuConfig")
|
localStorage.getItem(`qiniuConfig`)
|
||||||
);
|
)
|
||||||
const token = getQiniuToken(accessKey, secretKey, {
|
const token = getQiniuToken(accessKey, secretKey, {
|
||||||
scope: bucket,
|
scope: bucket,
|
||||||
deadline: Math.trunc(new Date().getTime() / 1000) + 3600,
|
deadline: Math.trunc(new Date().getTime() / 1000) + 3600,
|
||||||
});
|
})
|
||||||
const dir = path ? `${path}/` : "";
|
const dir = path ? `${path}/` : ``
|
||||||
const dateFilename = dir + getDateFilename(file.name);
|
const dateFilename = dir + getDateFilename(file.name)
|
||||||
const observable = qiniu.upload(file, dateFilename, token, {}, { region });
|
const observable = qiniu.upload(file, dateFilename, token, {}, { region })
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
observable.subscribe({
|
observable.subscribe({
|
||||||
next: (result) => {
|
next: (result) => {
|
||||||
console.log(result);
|
console.log(result)
|
||||||
},
|
},
|
||||||
error: (err) => {
|
error: (err) => {
|
||||||
reject(err.message);
|
reject(err.message)
|
||||||
},
|
},
|
||||||
complete: (result) => {
|
complete: (result) => {
|
||||||
resolve(`${domain}/${result.key}`);
|
resolve(`${domain}/${result.key}`)
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
@ -170,23 +167,23 @@ async function qiniuUpload(file) {
|
|||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
async function aliOSSFileUpload(content, filename) {
|
async function aliOSSFileUpload(content, filename) {
|
||||||
const dateFilename = getDateFilename(filename);
|
const dateFilename = getDateFilename(filename)
|
||||||
const { region, bucket, accessKeyId, accessKeySecret, cdnHost, path } =
|
const { region, bucket, accessKeyId, accessKeySecret, cdnHost, path } =
|
||||||
JSON.parse(localStorage.getItem("aliOSSConfig"));
|
JSON.parse(localStorage.getItem(`aliOSSConfig`))
|
||||||
const buffer = Buffer(content, "base64");
|
const buffer = Buffer(content, `base64`)
|
||||||
const dir = `${path}/${dateFilename}`;
|
const dir = `${path}/${dateFilename}`
|
||||||
const client = new OSS({
|
const client = new OSS({
|
||||||
region,
|
region,
|
||||||
bucket,
|
bucket,
|
||||||
accessKeyId,
|
accessKeyId,
|
||||||
accessKeySecret,
|
accessKeySecret,
|
||||||
});
|
})
|
||||||
try {
|
try {
|
||||||
const res = await client.put(dir, buffer);
|
const res = await client.put(dir, buffer)
|
||||||
if (cdnHost === "") return res.url;
|
if (cdnHost === ``) return res.url
|
||||||
return `${cdnHost}/${path === "" ? dateFilename : dir}`;
|
return `${cdnHost}/${path === `` ? dateFilename : dir}`
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return Promise.reject(e);
|
return Promise.reject(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,14 +192,14 @@ async function aliOSSFileUpload(content, filename) {
|
|||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
async function txCOSFileUpload(file) {
|
async function txCOSFileUpload(file) {
|
||||||
const dateFilename = getDateFilename(file.name);
|
const dateFilename = getDateFilename(file.name)
|
||||||
const { secretId, secretKey, bucket, region, path, cdnHost } = JSON.parse(
|
const { secretId, secretKey, bucket, region, path, cdnHost } = JSON.parse(
|
||||||
localStorage.getItem("txCOSConfig")
|
localStorage.getItem(`txCOSConfig`)
|
||||||
);
|
)
|
||||||
const cos = new COS({
|
const cos = new COS({
|
||||||
SecretId: secretId,
|
SecretId: secretId,
|
||||||
SecretKey: secretKey,
|
SecretKey: secretKey,
|
||||||
});
|
})
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
cos.putObject(
|
cos.putObject(
|
||||||
{
|
{
|
||||||
@ -213,19 +210,19 @@ async function txCOSFileUpload(file) {
|
|||||||
},
|
},
|
||||||
function (err, data) {
|
function (err, data) {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err);
|
reject(err)
|
||||||
} else if (cdnHost) {
|
} else if (cdnHost) {
|
||||||
resolve(
|
resolve(
|
||||||
path == ""
|
path == ``
|
||||||
? `${cdnHost}/${dateFilename}`
|
? `${cdnHost}/${dateFilename}`
|
||||||
: `${cdnHost}/${path}/${dateFilename}`
|
: `${cdnHost}/${path}/${dateFilename}`
|
||||||
);
|
)
|
||||||
} else {
|
} else {
|
||||||
resolve(`https://${data.Location}`);
|
resolve(`https://${data.Location}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
)
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
@ -233,41 +230,41 @@ async function txCOSFileUpload(file) {
|
|||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
async function minioFileUpload(content, filename) {
|
async function minioFileUpload(content, filename) {
|
||||||
const dateFilename = getDateFilename(filename);
|
const dateFilename = getDateFilename(filename)
|
||||||
const { endpoint, port, useSSL, bucket, accessKey, secretKey } = JSON.parse(
|
const { endpoint, port, useSSL, bucket, accessKey, secretKey } = JSON.parse(
|
||||||
localStorage.getItem("minioConfig")
|
localStorage.getItem(`minioConfig`)
|
||||||
);
|
)
|
||||||
const buffer = Buffer(content, "base64");
|
const buffer = Buffer(content, `base64`)
|
||||||
const conf = {
|
const conf = {
|
||||||
endPoint: endpoint,
|
endPoint: endpoint,
|
||||||
useSSL: useSSL,
|
useSSL: useSSL,
|
||||||
accessKey: accessKey,
|
accessKey: accessKey,
|
||||||
secretKey: secretKey,
|
secretKey: secretKey,
|
||||||
};
|
}
|
||||||
const p = Number(port || 0);
|
const p = Number(port || 0)
|
||||||
const isCustomPort = p > 0 && p !== 80 && p !== 443;
|
const isCustomPort = p > 0 && p !== 80 && p !== 443
|
||||||
if (isCustomPort) {
|
if (isCustomPort) {
|
||||||
conf.port = p;
|
conf.port = p
|
||||||
}
|
}
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const minioClient = new Minio.Client(conf);
|
const minioClient = new Minio.Client(conf)
|
||||||
try {
|
try {
|
||||||
minioClient.putObject(bucket, dateFilename, buffer, function (e) {
|
minioClient.putObject(bucket, dateFilename, buffer, function (e) {
|
||||||
if (e) {
|
if (e) {
|
||||||
reject(e);
|
reject(e)
|
||||||
}
|
}
|
||||||
const host = `${useSSL ? "https://" : "http://"}${endpoint}${
|
const host = `${useSSL ? `https://` : `http://`}${endpoint}${
|
||||||
isCustomPort ? ":" + port : ""
|
isCustomPort ? `:` + port : ``
|
||||||
}`;
|
}`
|
||||||
const url = `${host}/${bucket}/${dateFilename}`;
|
const url = `${host}/${bucket}/${dateFilename}`
|
||||||
// console.log("文件上传成功: ", url)
|
// console.log("文件上传成功: ", url)
|
||||||
resolve(url);
|
resolve(url)
|
||||||
// return `${endpoint}/${bucket}/${dateFilename}`;
|
// return `${endpoint}/${bucket}/${dateFilename}`;
|
||||||
});
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
reject(e);
|
reject(e)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
@ -279,7 +276,7 @@ async function formCustomUpload(content, file) {
|
|||||||
async (CUSTOM_ARG) => {
|
async (CUSTOM_ARG) => {
|
||||||
${localStorage.getItem(`formCustomConfig`)}
|
${localStorage.getItem(`formCustomConfig`)}
|
||||||
}
|
}
|
||||||
`;
|
`
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const exportObj = {
|
const exportObj = {
|
||||||
content, // 待上传图片的 base64
|
content, // 待上传图片的 base64
|
||||||
@ -298,40 +295,40 @@ async function formCustomUpload(content, file) {
|
|||||||
},
|
},
|
||||||
okCb: resolve, // 重要: 上传成功后给此回调传 url 即可
|
okCb: resolve, // 重要: 上传成功后给此回调传 url 即可
|
||||||
errCb: reject, // 上传失败调用的函数
|
errCb: reject, // 上传失败调用的函数
|
||||||
};
|
}
|
||||||
eval(str)(exportObj).catch((err) => {
|
eval(str)(exportObj).catch((err) => {
|
||||||
console.error(err);
|
console.error(err)
|
||||||
reject(err);
|
reject(err)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function fileUpload(content, file) {
|
function fileUpload(content, file) {
|
||||||
const imgHost = localStorage.getItem("imgHost");
|
const imgHost = localStorage.getItem(`imgHost`)
|
||||||
!imgHost && localStorage.setItem("imgHost", "default");
|
!imgHost && localStorage.setItem(`imgHost`, `default`)
|
||||||
switch (imgHost) {
|
switch (imgHost) {
|
||||||
case "aliOSS":
|
case `aliOSS`:
|
||||||
return aliOSSFileUpload(content, file.name);
|
return aliOSSFileUpload(content, file.name)
|
||||||
case "minio":
|
case `minio`:
|
||||||
return minioFileUpload(content, file.name);
|
return minioFileUpload(content, file.name)
|
||||||
case "txCOS":
|
case `txCOS`:
|
||||||
return txCOSFileUpload(file);
|
return txCOSFileUpload(file)
|
||||||
case "qiniu":
|
case `qiniu`:
|
||||||
return qiniuUpload(file);
|
return qiniuUpload(file)
|
||||||
case "gitee":
|
case `gitee`:
|
||||||
return giteeUpload(content, file.name);
|
return giteeUpload(content, file.name)
|
||||||
case "github":
|
case `github`:
|
||||||
return ghFileUpload(content, file.name);
|
return ghFileUpload(content, file.name)
|
||||||
case "formCustom":
|
case `formCustom`:
|
||||||
return formCustomUpload(content, file);
|
return formCustomUpload(content, file)
|
||||||
default:
|
default:
|
||||||
// return file.size / 1024 < 1024
|
// return file.size / 1024 < 1024
|
||||||
// ? giteeUpload(content, file.name)
|
// ? giteeUpload(content, file.name)
|
||||||
// : ghFileUpload(content, file.name);
|
// : ghFileUpload(content, file.name);
|
||||||
return ghFileUpload(content, file.name);
|
return ghFileUpload(content, file.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
fileUpload,
|
fileUpload,
|
||||||
};
|
}
|
||||||
|
@ -1,89 +1,87 @@
|
|||||||
export default {
|
export default {
|
||||||
builtinFonts: [
|
builtinFonts: [
|
||||||
{
|
{
|
||||||
label: "无衬线",
|
label: `无衬线`,
|
||||||
value:
|
value: `-apple-system-font,BlinkMacSystemFont, Helvetica Neue, PingFang SC, Hiragino Sans GB , Microsoft YaHei UI , Microsoft YaHei ,Arial,sans-serif`,
|
||||||
"-apple-system-font,BlinkMacSystemFont, Helvetica Neue, PingFang SC, Hiragino Sans GB , Microsoft YaHei UI , Microsoft YaHei ,Arial,sans-serif",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "衬线",
|
label: `衬线`,
|
||||||
value:
|
value: `Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, 'PingFang SC', Cambria, Cochin, Georgia, Times, 'Times New Roman', serif`,
|
||||||
"Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, 'PingFang SC', Cambria, Cochin, Georgia, Times, 'Times New Roman', serif",
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
sizeOption: [
|
sizeOption: [
|
||||||
{
|
{
|
||||||
label: "12px",
|
label: `12px`,
|
||||||
value: "12px",
|
value: `12px`,
|
||||||
desc: "更小",
|
desc: `更小`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "13px",
|
label: `13px`,
|
||||||
value: "13px",
|
value: `13px`,
|
||||||
desc: "稍小",
|
desc: `稍小`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "14px",
|
label: `14px`,
|
||||||
value: "14px",
|
value: `14px`,
|
||||||
desc: "推荐",
|
desc: `推荐`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "15px",
|
label: `15px`,
|
||||||
value: "15px",
|
value: `15px`,
|
||||||
desc: "稍大",
|
desc: `稍大`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "16px",
|
label: `16px`,
|
||||||
value: "16px",
|
value: `16px`,
|
||||||
desc: "更大",
|
desc: `更大`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
colorOption: [
|
colorOption: [
|
||||||
{
|
{
|
||||||
label: "经典蓝",
|
label: `经典蓝`,
|
||||||
value: "rgba(15, 76, 129, 1)",
|
value: `rgba(15, 76, 129, 1)`,
|
||||||
desc: "最新流行",
|
desc: `最新流行`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "翡翠绿",
|
label: `翡翠绿`,
|
||||||
value: "rgba(0, 152, 116, 1)",
|
value: `rgba(0, 152, 116, 1)`,
|
||||||
desc: "优雅清新",
|
desc: `优雅清新`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "活力橘",
|
label: `活力橘`,
|
||||||
value: "rgba(250, 81, 81, 1)",
|
value: `rgba(250, 81, 81, 1)`,
|
||||||
desc: "热情活泼",
|
desc: `热情活泼`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
codeThemeOption: [
|
codeThemeOption: [
|
||||||
{
|
{
|
||||||
label: "github",
|
label: `github`,
|
||||||
value: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/github.min.css",
|
value: `https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/github.min.css`,
|
||||||
desc: "light",
|
desc: `light`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "solarized-light",
|
label: `solarized-light`,
|
||||||
value: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/base16/solarized-light.min.css",
|
value: `https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/base16/solarized-light.min.css`,
|
||||||
desc: "light",
|
desc: `light`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "atom-one-dark",
|
label: `atom-one-dark`,
|
||||||
value: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/atom-one-dark.min.css",
|
value: `https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/atom-one-dark.min.css`,
|
||||||
desc: "dark",
|
desc: `dark`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "obsidian",
|
label: `obsidian`,
|
||||||
value: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/obsidian.min.css",
|
value: `https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/obsidian.min.css`,
|
||||||
desc: "dark",
|
desc: `dark`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "vs2015",
|
label: `vs2015`,
|
||||||
value: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/vs2015.min.css",
|
value: `https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/vs2015.min.css`,
|
||||||
desc: "dark",
|
desc: `dark`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
form: {
|
form: {
|
||||||
rows: 1,
|
rows: 1,
|
||||||
cols: 1,
|
cols: 1,
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
import juice from "juice";
|
import juice from 'juice'
|
||||||
|
|
||||||
export function solveWeChatImage() {
|
export function solveWeChatImage() {
|
||||||
const clipboardDiv = document.getElementById("output");
|
const clipboardDiv = document.getElementById(`output`)
|
||||||
const images = clipboardDiv.getElementsByTagName("img");
|
const images = clipboardDiv.getElementsByTagName(`img`)
|
||||||
for (let i = 0; i < images.length; i++) {
|
for (let i = 0; i < images.length; i++) {
|
||||||
const image = images[i];
|
const image = images[i]
|
||||||
const width = image.getAttribute("width");
|
const width = image.getAttribute(`width`)
|
||||||
const height = image.getAttribute("height");
|
const height = image.getAttribute(`height`)
|
||||||
image.removeAttribute("width");
|
image.removeAttribute(`width`)
|
||||||
image.removeAttribute("height");
|
image.removeAttribute(`height`)
|
||||||
image.style.width = width;
|
image.style.width = width
|
||||||
image.style.height = height;
|
image.style.height = height
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export function solveHtml() {
|
export function solveHtml() {
|
||||||
const element = document.getElementById("output-wrapper");
|
const element = document.getElementById(`output-wrapper`)
|
||||||
let html = element.innerHTML;
|
let html = element.innerHTML
|
||||||
let res = "";
|
let res = ``
|
||||||
res = juice.inlineContent(html, {
|
res = juice.inlineContent(html, {
|
||||||
inlinePseudoElements: true,
|
inlinePseudoElements: true,
|
||||||
preserveImportant: true,
|
preserveImportant: true,
|
||||||
});
|
})
|
||||||
return res;
|
return res
|
||||||
}
|
}
|
||||||
|
@ -1,192 +1,192 @@
|
|||||||
let baseColor = "#3f3f3f"
|
let baseColor = `#3f3f3f`
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
BASE: {
|
BASE: {
|
||||||
"text-align": "left",
|
'text-align': `left`,
|
||||||
"line-height": "1.75"
|
'line-height': `1.75`,
|
||||||
},
|
},
|
||||||
block: {
|
block: {
|
||||||
// 一级标题样式
|
// 一级标题样式
|
||||||
h1: {
|
h1: {
|
||||||
"font-size": "1.2em",
|
'font-size': `1.2em`,
|
||||||
"text-align": "center",
|
'text-align': `center`,
|
||||||
"font-weight": "bold",
|
'font-weight': `bold`,
|
||||||
display: "table",
|
display: `table`,
|
||||||
margin: "2em auto 1em",
|
margin: `2em auto 1em`,
|
||||||
padding: "0 1em",
|
padding: `0 1em`,
|
||||||
"border-bottom": "2px solid rgba(0, 152, 116, 0.9)",
|
'border-bottom': `2px solid rgba(0, 152, 116, 0.9)`,
|
||||||
color: baseColor,
|
color: baseColor,
|
||||||
},
|
},
|
||||||
|
|
||||||
// 二级标题样式
|
// 二级标题样式
|
||||||
h2: {
|
h2: {
|
||||||
"font-size": "1.2em",
|
'font-size': `1.2em`,
|
||||||
"text-align": "center",
|
'text-align': `center`,
|
||||||
"font-weight": "bold",
|
'font-weight': `bold`,
|
||||||
display: "table",
|
display: `table`,
|
||||||
margin: "4em auto 2em",
|
margin: `4em auto 2em`,
|
||||||
padding: "0 0.2em",
|
padding: `0 0.2em`,
|
||||||
background: "rgba(0, 152, 116, 0.9)",
|
background: `rgba(0, 152, 116, 0.9)`,
|
||||||
color: "#fff",
|
color: `#fff`,
|
||||||
},
|
},
|
||||||
|
|
||||||
// 三级标题样式
|
// 三级标题样式
|
||||||
h3: {
|
h3: {
|
||||||
"font-weight": "bold",
|
'font-weight': `bold`,
|
||||||
"font-size": "1.1em",
|
'font-size': `1.1em`,
|
||||||
margin: "2em 8px 0.75em 0",
|
margin: `2em 8px 0.75em 0`,
|
||||||
"line-height": "1.2",
|
'line-height': `1.2`,
|
||||||
"padding-left": "8px",
|
'padding-left': `8px`,
|
||||||
"border-left": "3px solid rgba(0, 152, 116, 0.9)",
|
'border-left': `3px solid rgba(0, 152, 116, 0.9)`,
|
||||||
color: baseColor,
|
color: baseColor,
|
||||||
},
|
},
|
||||||
|
|
||||||
// 四级标题样式
|
// 四级标题样式
|
||||||
h4: {
|
h4: {
|
||||||
"font-weight": "bold",
|
'font-weight': `bold`,
|
||||||
"font-size": "1em",
|
'font-size': `1em`,
|
||||||
margin: "2em 8px 0.5em",
|
margin: `2em 8px 0.5em`,
|
||||||
color: "rgba(66, 185, 131, 0.9)",
|
color: `rgba(66, 185, 131, 0.9)`,
|
||||||
},
|
},
|
||||||
|
|
||||||
// 段落样式
|
// 段落样式
|
||||||
p: {
|
p: {
|
||||||
margin: "1.5em 8px",
|
margin: `1.5em 8px`,
|
||||||
"letter-spacing": "0.1em",
|
'letter-spacing': `0.1em`,
|
||||||
color: baseColor,
|
color: baseColor,
|
||||||
},
|
},
|
||||||
|
|
||||||
// 引用样式
|
// 引用样式
|
||||||
blockquote: {
|
blockquote: {
|
||||||
"font-style": "normal",
|
'font-style': `normal`,
|
||||||
"border-left": "none",
|
'border-left': `none`,
|
||||||
padding: "1em",
|
padding: `1em`,
|
||||||
"border-radius": "8px",
|
'border-radius': `8px`,
|
||||||
color: "rgba(0,0,0,0.5)",
|
color: `rgba(0,0,0,0.5)`,
|
||||||
background: "#f7f7f7",
|
background: `#f7f7f7`,
|
||||||
margin: "2em 8px",
|
margin: `2em 8px`,
|
||||||
},
|
},
|
||||||
|
|
||||||
blockquote_p: {
|
blockquote_p: {
|
||||||
"letter-spacing": "0.1em",
|
'letter-spacing': `0.1em`,
|
||||||
color: "rgb(80, 80, 80)",
|
color: `rgb(80, 80, 80)`,
|
||||||
"font-size": "1em",
|
'font-size': `1em`,
|
||||||
display: "block",
|
display: `block`,
|
||||||
},
|
},
|
||||||
code_pre: {
|
code_pre: {
|
||||||
"font-size": "14px",
|
'font-size': `14px`,
|
||||||
"overflow-x": "auto",
|
'overflow-x': `auto`,
|
||||||
"border-radius": "8px",
|
'border-radius': `8px`,
|
||||||
padding: "1em",
|
padding: `1em`,
|
||||||
"line-height": "1.5",
|
'line-height': `1.5`,
|
||||||
margin: "10px 8px"
|
margin: `10px 8px`,
|
||||||
},
|
},
|
||||||
code: {
|
code: {
|
||||||
"margin": 0,
|
margin: 0,
|
||||||
"white-space": "nowrap",
|
'white-space': `nowrap`,
|
||||||
"font-family": "Menlo, Operator Mono, Consolas, Monaco, monospace"
|
'font-family': `Menlo, Operator Mono, Consolas, Monaco, monospace`,
|
||||||
},
|
},
|
||||||
|
|
||||||
image: {
|
image: {
|
||||||
"border-radius": "4px",
|
'border-radius': `4px`,
|
||||||
display: "block",
|
display: `block`,
|
||||||
margin: "0.1em auto 0.5em",
|
margin: `0.1em auto 0.5em`,
|
||||||
width: "100% !important",
|
width: `100% !important`,
|
||||||
},
|
},
|
||||||
|
|
||||||
ol: {
|
ol: {
|
||||||
"margin-left": "0",
|
'margin-left': `0`,
|
||||||
"padding-left": "1em",
|
'padding-left': `1em`,
|
||||||
color: baseColor,
|
color: baseColor,
|
||||||
},
|
},
|
||||||
|
|
||||||
ul: {
|
ul: {
|
||||||
"margin-left": "0",
|
'margin-left': `0`,
|
||||||
"padding-left": "1em",
|
'padding-left': `1em`,
|
||||||
"list-style": "circle",
|
'list-style': `circle`,
|
||||||
color: baseColor,
|
color: baseColor,
|
||||||
},
|
},
|
||||||
|
|
||||||
footnotes: {
|
footnotes: {
|
||||||
margin: "0.5em 8px",
|
margin: `0.5em 8px`,
|
||||||
"font-size": "80%",
|
'font-size': `80%`,
|
||||||
color: baseColor,
|
color: baseColor,
|
||||||
},
|
},
|
||||||
|
|
||||||
figure: {
|
figure: {
|
||||||
margin: "1.5em 8px",
|
margin: `1.5em 8px`,
|
||||||
color: baseColor,
|
color: baseColor,
|
||||||
},
|
},
|
||||||
hr: {
|
hr: {
|
||||||
"border-style": "solid",
|
'border-style': `solid`,
|
||||||
"border-width": "1px 0 0",
|
'border-width': `1px 0 0`,
|
||||||
"border-color": "rgba(0,0,0,0.1)",
|
'border-color': `rgba(0,0,0,0.1)`,
|
||||||
"-webkit-transform-origin": "0 0",
|
'-webkit-transform-origin': `0 0`,
|
||||||
"-webkit-transform": "scale(1, 0.5)",
|
'-webkit-transform': `scale(1, 0.5)`,
|
||||||
"transform-origin": "0 0",
|
'transform-origin': `0 0`,
|
||||||
transform: "scale(1, 0.5)",
|
transform: `scale(1, 0.5)`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
inline: {
|
inline: {
|
||||||
listitem: {
|
listitem: {
|
||||||
"text-indent": "-1em",
|
'text-indent': `-1em`,
|
||||||
display: "block",
|
display: `block`,
|
||||||
margin: "0.2em 8px",
|
margin: `0.2em 8px`,
|
||||||
color: baseColor,
|
color: baseColor,
|
||||||
},
|
},
|
||||||
|
|
||||||
codespan: {
|
codespan: {
|
||||||
"font-size": "90%",
|
'font-size': `90%`,
|
||||||
"white-space": "pre",
|
'white-space': `pre`,
|
||||||
color: "#d14",
|
color: `#d14`,
|
||||||
background: "rgba(27,31,35,.05)",
|
background: `rgba(27,31,35,.05)`,
|
||||||
padding: "3px 5px",
|
padding: `3px 5px`,
|
||||||
"border-radius": "4px",
|
'border-radius': `4px`,
|
||||||
},
|
},
|
||||||
|
|
||||||
link: {
|
link: {
|
||||||
color: "#576b95",
|
color: `#576b95`,
|
||||||
},
|
},
|
||||||
|
|
||||||
wx_link: {
|
wx_link: {
|
||||||
color: "#576b95",
|
color: `#576b95`,
|
||||||
"text-decoration": "none",
|
'text-decoration': `none`,
|
||||||
},
|
},
|
||||||
|
|
||||||
// 字体加粗样式
|
// 字体加粗样式
|
||||||
strong: {
|
strong: {
|
||||||
color: "rgba(15, 76, 129, 0.9)",
|
color: `rgba(15, 76, 129, 0.9)`,
|
||||||
"font-weight": "bold",
|
'font-weight': `bold`,
|
||||||
},
|
},
|
||||||
|
|
||||||
table: {
|
table: {
|
||||||
"border-collapse": "collapse",
|
'border-collapse': `collapse`,
|
||||||
"text-align": "center",
|
'text-align': `center`,
|
||||||
margin: "1em 8px",
|
margin: `1em 8px`,
|
||||||
color: baseColor,
|
color: baseColor,
|
||||||
},
|
},
|
||||||
|
|
||||||
thead: {
|
thead: {
|
||||||
background: "rgba(0, 0, 0, 0.05)",
|
background: `rgba(0, 0, 0, 0.05)`,
|
||||||
"font-weight": "bold",
|
'font-weight': `bold`,
|
||||||
color: baseColor,
|
color: baseColor,
|
||||||
},
|
},
|
||||||
|
|
||||||
td: {
|
td: {
|
||||||
border: "1px solid #dfdfdf",
|
border: `1px solid #dfdfdf`,
|
||||||
padding: "0.25em 0.5em",
|
padding: `0.25em 0.5em`,
|
||||||
color: baseColor,
|
color: baseColor,
|
||||||
},
|
},
|
||||||
|
|
||||||
footnote: {
|
footnote: {
|
||||||
"font-size": "12px",
|
'font-size': `12px`,
|
||||||
color: baseColor,
|
color: baseColor,
|
||||||
},
|
},
|
||||||
|
|
||||||
figcaption: {
|
figcaption: {
|
||||||
"text-align": "center",
|
'text-align': `center`,
|
||||||
color: "#888",
|
color: `#888`,
|
||||||
"font-size": "0.8em",
|
'font-size': `0.8em`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
@ -1,31 +1,31 @@
|
|||||||
export function utf16to8(str) {
|
export function utf16to8(str) {
|
||||||
var out, i, len, c;
|
var out, i, len, c
|
||||||
out = "";
|
out = ``
|
||||||
len = str.length;
|
len = str.length
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
c = str.charCodeAt(i);
|
c = str.charCodeAt(i)
|
||||||
if (c >= 0x0001 && c <= 0x007f) {
|
if (c >= 0x0001 && c <= 0x007f) {
|
||||||
out += str.charAt(i);
|
out += str.charAt(i)
|
||||||
} else if (c > 0x07ff) {
|
} else if (c > 0x07ff) {
|
||||||
out += String.fromCharCode(0xe0 | ((c >> 12) & 0x0f));
|
out += String.fromCharCode(0xe0 | ((c >> 12) & 0x0f))
|
||||||
out += String.fromCharCode(0x80 | ((c >> 6) & 0x3f));
|
out += String.fromCharCode(0x80 | ((c >> 6) & 0x3f))
|
||||||
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3f));
|
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3f))
|
||||||
} else {
|
} else {
|
||||||
out += String.fromCharCode(0xc0 | ((c >> 6) & 0x1f));
|
out += String.fromCharCode(0xc0 | ((c >> 6) & 0x1f))
|
||||||
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3f));
|
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out;
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
export function utf8to16(str) {
|
export function utf8to16(str) {
|
||||||
var out, i, len, c;
|
var out, i, len, c
|
||||||
var char2, char3;
|
var char2, char3
|
||||||
out = "";
|
out = ``
|
||||||
len = str.length;
|
len = str.length
|
||||||
i = 0;
|
i = 0
|
||||||
while (i < len) {
|
while (i < len) {
|
||||||
c = str.charCodeAt(i++);
|
c = str.charCodeAt(i++)
|
||||||
switch (c >> 4) {
|
switch (c >> 4) {
|
||||||
case 0:
|
case 0:
|
||||||
case 1:
|
case 1:
|
||||||
@ -36,29 +36,28 @@ export function utf8to16(str) {
|
|||||||
case 6:
|
case 6:
|
||||||
case 7:
|
case 7:
|
||||||
// 0xxxxxxx
|
// 0xxxxxxx
|
||||||
out += str.charAt(i - 1);
|
out += str.charAt(i - 1)
|
||||||
break;
|
break
|
||||||
case 12:
|
case 12:
|
||||||
case 13:
|
case 13:
|
||||||
// 110x xxxx 10xx xxxx
|
// 110x xxxx 10xx xxxx
|
||||||
char2 = str.charCodeAt(i++);
|
char2 = str.charCodeAt(i++)
|
||||||
out += String.fromCharCode(((c & 0x1f) << 6) | (char2 & 0x3f));
|
out += String.fromCharCode(((c & 0x1f) << 6) | (char2 & 0x3f))
|
||||||
break;
|
break
|
||||||
case 14:
|
case 14:
|
||||||
// 1110 xxxx 10xx xxxx 10xx xxxx
|
// 1110 xxxx 10xx xxxx 10xx xxxx
|
||||||
char2 = str.charCodeAt(i++);
|
char2 = str.charCodeAt(i++)
|
||||||
char3 = str.charCodeAt(i++);
|
char3 = str.charCodeAt(i++)
|
||||||
out += String.fromCharCode(
|
out += String.fromCharCode(
|
||||||
((c & 0x0f) << 12) | ((char2 & 0x3f) << 6) | ((char3 & 0x3f) << 0)
|
((c & 0x0f) << 12) | ((char2 & 0x3f) << 6) | ((char3 & 0x3f) << 0)
|
||||||
);
|
)
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out;
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
const base64EncodeChars =
|
const base64EncodeChars = `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_`
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
||||||
const base64DecodeChars = new Array(
|
const base64DecodeChars = new Array(
|
||||||
-1,
|
-1,
|
||||||
-1,
|
-1,
|
||||||
@ -188,78 +187,78 @@ const base64DecodeChars = new Array(
|
|||||||
-1,
|
-1,
|
||||||
-1,
|
-1,
|
||||||
-1
|
-1
|
||||||
);
|
)
|
||||||
export function base64encode(str) {
|
export function base64encode(str) {
|
||||||
var out, i, len;
|
var out, i, len
|
||||||
var c1, c2, c3;
|
var c1, c2, c3
|
||||||
len = str.length;
|
len = str.length
|
||||||
i = 0;
|
i = 0
|
||||||
out = "";
|
out = ``
|
||||||
while (i < len) {
|
while (i < len) {
|
||||||
c1 = str.charCodeAt(i++) & 0xff;
|
c1 = str.charCodeAt(i++) & 0xff
|
||||||
if (i == len) {
|
if (i == len) {
|
||||||
out += base64EncodeChars.charAt(c1 >> 2);
|
out += base64EncodeChars.charAt(c1 >> 2)
|
||||||
out += base64EncodeChars.charAt((c1 & 0x3) << 4);
|
out += base64EncodeChars.charAt((c1 & 0x3) << 4)
|
||||||
out += "==";
|
out += `==`
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
c2 = str.charCodeAt(i++);
|
c2 = str.charCodeAt(i++)
|
||||||
if (i == len) {
|
if (i == len) {
|
||||||
out += base64EncodeChars.charAt(c1 >> 2);
|
out += base64EncodeChars.charAt(c1 >> 2)
|
||||||
out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4));
|
out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4))
|
||||||
out += base64EncodeChars.charAt((c2 & 0xf) << 2);
|
out += base64EncodeChars.charAt((c2 & 0xf) << 2)
|
||||||
out += "=";
|
out += `=`
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
c3 = str.charCodeAt(i++);
|
c3 = str.charCodeAt(i++)
|
||||||
out += base64EncodeChars.charAt(c1 >> 2);
|
out += base64EncodeChars.charAt(c1 >> 2)
|
||||||
out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4));
|
out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4))
|
||||||
out += base64EncodeChars.charAt(((c2 & 0xf) << 2) | ((c3 & 0xc0) >> 6));
|
out += base64EncodeChars.charAt(((c2 & 0xf) << 2) | ((c3 & 0xc0) >> 6))
|
||||||
out += base64EncodeChars.charAt(c3 & 0x3f);
|
out += base64EncodeChars.charAt(c3 & 0x3f)
|
||||||
}
|
}
|
||||||
return out;
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
export function base64decode(str) {
|
export function base64decode(str) {
|
||||||
var c1, c2, c3, c4;
|
var c1, c2, c3, c4
|
||||||
var i, len, out;
|
var i, len, out
|
||||||
len = str.length;
|
len = str.length
|
||||||
i = 0;
|
i = 0
|
||||||
out = "";
|
out = ``
|
||||||
while (i < len) {
|
while (i < len) {
|
||||||
/* c1 */
|
/* c1 */
|
||||||
do {
|
do {
|
||||||
c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
|
c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff]
|
||||||
} while (i < len && c1 == -1);
|
} while (i < len && c1 == -1)
|
||||||
if (c1 == -1) break;
|
if (c1 == -1) break
|
||||||
/* c2 */
|
/* c2 */
|
||||||
do {
|
do {
|
||||||
c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
|
c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff]
|
||||||
} while (i < len && c2 == -1);
|
} while (i < len && c2 == -1)
|
||||||
if (c2 == -1) break;
|
if (c2 == -1) break
|
||||||
out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
|
out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4))
|
||||||
/* c3 */
|
/* c3 */
|
||||||
do {
|
do {
|
||||||
c3 = str.charCodeAt(i++) & 0xff;
|
c3 = str.charCodeAt(i++) & 0xff
|
||||||
if (c3 == 61) return out;
|
if (c3 == 61) return out
|
||||||
c3 = base64DecodeChars[c3];
|
c3 = base64DecodeChars[c3]
|
||||||
} while (i < len && c3 == -1);
|
} while (i < len && c3 == -1)
|
||||||
if (c3 == -1) break;
|
if (c3 == -1) break
|
||||||
out += String.fromCharCode(((c2 & 0xf) << 4) | ((c3 & 0x3c) >> 2));
|
out += String.fromCharCode(((c2 & 0xf) << 4) | ((c3 & 0x3c) >> 2))
|
||||||
/* c4 */
|
/* c4 */
|
||||||
do {
|
do {
|
||||||
c4 = str.charCodeAt(i++) & 0xff;
|
c4 = str.charCodeAt(i++) & 0xff
|
||||||
if (c4 == 61) return out;
|
if (c4 == 61) return out
|
||||||
c4 = base64DecodeChars[c4];
|
c4 = base64DecodeChars[c4]
|
||||||
} while (i < len && c4 == -1);
|
} while (i < len && c4 == -1)
|
||||||
if (c4 == -1) break;
|
if (c4 == -1) break
|
||||||
out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
|
out += String.fromCharCode(((c3 & 0x03) << 6) | c4)
|
||||||
}
|
}
|
||||||
return out;
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
export function safe64(base64) {
|
export function safe64(base64) {
|
||||||
base64 = base64.replace(/\+/g, "-");
|
base64 = base64.replace(/\+/g, `-`)
|
||||||
base64 = base64.replace(/\//g, "_");
|
base64 = base64.replace(/\//g, `_`)
|
||||||
return base64;
|
return base64
|
||||||
}
|
}
|
||||||
|
@ -1,102 +1,105 @@
|
|||||||
import defaultTheme from "./themes/default-theme";
|
import defaultTheme from './themes/default-theme'
|
||||||
import prettier from "prettier/standalone";
|
import prettier from 'prettier/standalone'
|
||||||
import prettierMarkdown from "prettier/parser-markdown";
|
import prettierMarkdown from 'prettier/parser-markdown'
|
||||||
import prettierCss from "prettier/parser-postcss";
|
import prettierCss from 'prettier/parser-postcss'
|
||||||
|
|
||||||
// 设置自定义颜色
|
// 设置自定义颜色
|
||||||
export function setColorWithTemplate(template) {
|
export function setColorWithTemplate(template) {
|
||||||
return function (color) {
|
return function (color) {
|
||||||
let customTheme = JSON.parse(JSON.stringify(template));
|
let customTheme = JSON.parse(JSON.stringify(template))
|
||||||
customTheme.block.h1["border-bottom"] = `2px solid ${color}`;
|
customTheme.block.h1[`border-bottom`] = `2px solid ${color}`
|
||||||
customTheme.block.h2["background"] = color;
|
customTheme.block.h2[`background`] = color
|
||||||
customTheme.block.h3["border-left"] = `3px solid ${color}`;
|
customTheme.block.h3[`border-left`] = `3px solid ${color}`
|
||||||
customTheme.block.h4["color"] = color;
|
customTheme.block.h4[`color`] = color
|
||||||
customTheme.inline.strong["color"] = color;
|
customTheme.inline.strong[`color`] = color
|
||||||
return customTheme;
|
return customTheme
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const setColorWithCustomTemplate = function setColorWithCustomTemplate(
|
export const setColorWithCustomTemplate = function setColorWithCustomTemplate(
|
||||||
template,
|
template,
|
||||||
color
|
color
|
||||||
) {
|
) {
|
||||||
let customTheme = JSON.parse(JSON.stringify(template));
|
let customTheme = JSON.parse(JSON.stringify(template))
|
||||||
customTheme.block.h1["border-bottom"] = `2px solid ${color}`;
|
customTheme.block.h1[`border-bottom`] = `2px solid ${color}`
|
||||||
customTheme.block.h2["background"] = color;
|
customTheme.block.h2[`background`] = color
|
||||||
customTheme.block.h3["border-left"] = `3px solid ${color}`;
|
customTheme.block.h3[`border-left`] = `3px solid ${color}`
|
||||||
customTheme.block.h4["color"] = color;
|
customTheme.block.h4[`color`] = color
|
||||||
customTheme.inline.strong["color"] = color;
|
customTheme.inline.strong[`color`] = color
|
||||||
return customTheme;
|
return customTheme
|
||||||
};
|
}
|
||||||
|
|
||||||
// 设置自定义字体大小
|
// 设置自定义字体大小
|
||||||
export function setFontSizeWithTemplate(template) {
|
export function setFontSizeWithTemplate(template) {
|
||||||
return function (fontSize) {
|
return function (fontSize) {
|
||||||
let customTheme = JSON.parse(JSON.stringify(template));
|
let customTheme = JSON.parse(JSON.stringify(template))
|
||||||
customTheme.block.h1["font-size"] = `${fontSize * 1.14}px`;
|
customTheme.block.h1[`font-size`] = `${fontSize * 1.14}px`
|
||||||
customTheme.block.h2["font-size"] = `${fontSize * 1.1}px`;
|
customTheme.block.h2[`font-size`] = `${fontSize * 1.1}px`
|
||||||
customTheme.block.h3["font-size"] = `${fontSize}px`;
|
customTheme.block.h3[`font-size`] = `${fontSize}px`
|
||||||
customTheme.block.h4["font-size"] = `${fontSize}px`;
|
customTheme.block.h4[`font-size`] = `${fontSize}px`
|
||||||
return customTheme;
|
return customTheme
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const setColor = setColorWithTemplate(defaultTheme);
|
export const setColor = setColorWithTemplate(defaultTheme)
|
||||||
export const setFontSize = setFontSizeWithTemplate(defaultTheme);
|
export const setFontSize = setFontSizeWithTemplate(defaultTheme)
|
||||||
|
|
||||||
export function customCssWithTemplate(jsonString, color, theme) {
|
export function customCssWithTemplate(jsonString, color, theme) {
|
||||||
let customTheme = JSON.parse(JSON.stringify(theme));
|
let customTheme = JSON.parse(JSON.stringify(theme))
|
||||||
// block
|
// block
|
||||||
customTheme.block.h1["border-bottom"] = `2px solid ${color}`;
|
customTheme.block.h1[`border-bottom`] = `2px solid ${color}`
|
||||||
customTheme.block.h2["background"] = color;
|
customTheme.block.h2[`background`] = color
|
||||||
customTheme.block.h3["border-left"] = `3px solid ${color}`;
|
customTheme.block.h3[`border-left`] = `3px solid ${color}`
|
||||||
customTheme.block.h4["color"] = color;
|
customTheme.block.h4[`color`] = color
|
||||||
customTheme.inline.strong["color"] = color;
|
customTheme.inline.strong[`color`] = color
|
||||||
|
|
||||||
customTheme.block.h1 = Object.assign(customTheme.block.h1, jsonString.h1);
|
customTheme.block.h1 = Object.assign(customTheme.block.h1, jsonString.h1)
|
||||||
customTheme.block.h2 = Object.assign(customTheme.block.h2, jsonString.h2);
|
customTheme.block.h2 = Object.assign(customTheme.block.h2, jsonString.h2)
|
||||||
customTheme.block.h3 = Object.assign(customTheme.block.h3, jsonString.h3);
|
customTheme.block.h3 = Object.assign(customTheme.block.h3, jsonString.h3)
|
||||||
customTheme.block.h4 = Object.assign(customTheme.block.h4, jsonString.h4);
|
customTheme.block.h4 = Object.assign(customTheme.block.h4, jsonString.h4)
|
||||||
customTheme.block.code = Object.assign(customTheme.block.code, jsonString.code);
|
customTheme.block.code = Object.assign(
|
||||||
customTheme.block.p = Object.assign(customTheme.block.p, jsonString.p);
|
customTheme.block.code,
|
||||||
customTheme.block.hr = Object.assign(customTheme.block.hr, jsonString.hr);
|
jsonString.code
|
||||||
|
)
|
||||||
|
customTheme.block.p = Object.assign(customTheme.block.p, jsonString.p)
|
||||||
|
customTheme.block.hr = Object.assign(customTheme.block.hr, jsonString.hr)
|
||||||
customTheme.block.blockquote = Object.assign(
|
customTheme.block.blockquote = Object.assign(
|
||||||
customTheme.block.blockquote,
|
customTheme.block.blockquote,
|
||||||
jsonString.blockquote
|
jsonString.blockquote
|
||||||
);
|
)
|
||||||
customTheme.block.blockquote_p = Object.assign(
|
customTheme.block.blockquote_p = Object.assign(
|
||||||
customTheme.block.blockquote_p,
|
customTheme.block.blockquote_p,
|
||||||
jsonString.blockquote_p
|
jsonString.blockquote_p
|
||||||
);
|
)
|
||||||
customTheme.block.image = Object.assign(
|
customTheme.block.image = Object.assign(
|
||||||
customTheme.block.image,
|
customTheme.block.image,
|
||||||
jsonString.image
|
jsonString.image
|
||||||
);
|
)
|
||||||
|
|
||||||
// inline
|
// inline
|
||||||
customTheme.inline.strong = Object.assign(
|
customTheme.inline.strong = Object.assign(
|
||||||
customTheme.inline.strong,
|
customTheme.inline.strong,
|
||||||
jsonString.strong
|
jsonString.strong
|
||||||
);
|
)
|
||||||
customTheme.inline.codespan = Object.assign(
|
customTheme.inline.codespan = Object.assign(
|
||||||
customTheme.inline.codespan,
|
customTheme.inline.codespan,
|
||||||
jsonString.codespan
|
jsonString.codespan
|
||||||
);
|
)
|
||||||
customTheme.inline.link = Object.assign(
|
customTheme.inline.link = Object.assign(
|
||||||
customTheme.inline.link,
|
customTheme.inline.link,
|
||||||
jsonString.link
|
jsonString.link
|
||||||
);
|
)
|
||||||
customTheme.inline.wx_link = Object.assign(
|
customTheme.inline.wx_link = Object.assign(
|
||||||
customTheme.inline.wx_link,
|
customTheme.inline.wx_link,
|
||||||
jsonString.wx_link
|
jsonString.wx_link
|
||||||
);
|
)
|
||||||
customTheme.block.ul = Object.assign(customTheme.block.ul, jsonString.ul);
|
customTheme.block.ul = Object.assign(customTheme.block.ul, jsonString.ul)
|
||||||
customTheme.block.ol = Object.assign(customTheme.block.ol, jsonString.ol);
|
customTheme.block.ol = Object.assign(customTheme.block.ol, jsonString.ol)
|
||||||
customTheme.inline.listitem = Object.assign(
|
customTheme.inline.listitem = Object.assign(
|
||||||
customTheme.inline.listitem,
|
customTheme.inline.listitem,
|
||||||
jsonString.li
|
jsonString.li
|
||||||
);
|
)
|
||||||
return customTheme;
|
return customTheme
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -106,21 +109,21 @@ export function customCssWithTemplate(jsonString, color, theme) {
|
|||||||
*/
|
*/
|
||||||
export function css2json(css) {
|
export function css2json(css) {
|
||||||
// 移除CSS所有注释
|
// 移除CSS所有注释
|
||||||
let open, close;
|
let open, close
|
||||||
while (
|
while (
|
||||||
(open = css.indexOf("/*")) !== -1 &&
|
(open = css.indexOf(`/*`)) !== -1 &&
|
||||||
(close = css.indexOf("*/")) !== -1
|
(close = css.indexOf(`*/`)) !== -1
|
||||||
) {
|
) {
|
||||||
css = css.substring(0, open) + css.substring(close + 2);
|
css = css.substring(0, open) + css.substring(close + 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化返回值
|
// 初始化返回值
|
||||||
let json = {};
|
let json = {}
|
||||||
|
|
||||||
while (css.length > 0 && css.indexOf("{") !== -1 && css.indexOf("}") !== -1) {
|
while (css.length > 0 && css.indexOf(`{`) !== -1 && css.indexOf(`}`) !== -1) {
|
||||||
// 存储第一个左/右花括号的下标
|
// 存储第一个左/右花括号的下标
|
||||||
const lbracket = css.indexOf("{");
|
const lbracket = css.indexOf(`{`)
|
||||||
const rbracket = css.indexOf("}");
|
const rbracket = css.indexOf(`}`)
|
||||||
|
|
||||||
// 第一步:将声明转换为Object,如:
|
// 第一步:将声明转换为Object,如:
|
||||||
// `font: 'Times New Roman' 1em; color: #ff0000; margin-top: 1em;`
|
// `font: 'Times New Roman' 1em; color: #ff0000; margin-top: 1em;`
|
||||||
@ -128,26 +131,27 @@ export function css2json(css) {
|
|||||||
// `{"font": "'Times New Roman' 1em", "color": "#ff0000", "margin-top": "1em"}`
|
// `{"font": "'Times New Roman' 1em", "color": "#ff0000", "margin-top": "1em"}`
|
||||||
|
|
||||||
// 辅助方法:将array转为object
|
// 辅助方法:将array转为object
|
||||||
|
// eslint-disable-next-line no-inner-declarations
|
||||||
function toObject(array) {
|
function toObject(array) {
|
||||||
let ret = {};
|
let ret = {}
|
||||||
array.forEach((e) => {
|
array.forEach((e) => {
|
||||||
const index = e.indexOf(":");
|
const index = e.indexOf(`:`)
|
||||||
const property = e.substring(0, index).trim();
|
const property = e.substring(0, index).trim()
|
||||||
const value = e.substring(index + 1).trim();
|
const value = e.substring(index + 1).trim()
|
||||||
ret[property] = value;
|
ret[property] = value
|
||||||
});
|
})
|
||||||
return ret;
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// 切割声明块并移除空白符,然后放入数组中
|
// 切割声明块并移除空白符,然后放入数组中
|
||||||
let declarations = css
|
let declarations = css
|
||||||
.substring(lbracket + 1, rbracket)
|
.substring(lbracket + 1, rbracket)
|
||||||
.split(";")
|
.split(`;`)
|
||||||
.map((e) => e.trim())
|
.map((e) => e.trim())
|
||||||
.filter((e) => e.length > 0); // 移除所有""空值
|
.filter((e) => e.length > 0) // 移除所有""空值
|
||||||
|
|
||||||
// 转为Object对象
|
// 转为Object对象
|
||||||
declarations = toObject(declarations);
|
declarations = toObject(declarations)
|
||||||
|
|
||||||
// 第二步:选择器处理,每个选择器会与它对应的声明相关联,如:
|
// 第二步:选择器处理,每个选择器会与它对应的声明相关联,如:
|
||||||
// `h1, p#bar {color: red}`
|
// `h1, p#bar {color: red}`
|
||||||
@ -157,25 +161,25 @@ export function css2json(css) {
|
|||||||
let selectors = css
|
let selectors = css
|
||||||
.substring(0, lbracket)
|
.substring(0, lbracket)
|
||||||
// 以,切割,并移除空格:`"h1, p#bar, span.foo"` => ["h1", "p#bar", "span.foo"]
|
// 以,切割,并移除空格:`"h1, p#bar, span.foo"` => ["h1", "p#bar", "span.foo"]
|
||||||
.split(",")
|
.split(`,`)
|
||||||
.map((selector) => selector.trim());
|
.map((selector) => selector.trim())
|
||||||
|
|
||||||
// 迭代赋值
|
// 迭代赋值
|
||||||
selectors.forEach((selector) => {
|
selectors.forEach((selector) => {
|
||||||
// 若不存在,则先初始化
|
// 若不存在,则先初始化
|
||||||
if (!json[selector]) json[selector] = {};
|
if (!json[selector]) json[selector] = {}
|
||||||
// 赋值到JSON
|
// 赋值到JSON
|
||||||
Object.keys(declarations).forEach((key) => {
|
Object.keys(declarations).forEach((key) => {
|
||||||
json[selector][key] = declarations[key];
|
json[selector][key] = declarations[key]
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
// 继续下个声明块
|
// 继续下个声明块
|
||||||
css = css.slice(rbracket + 1).trim();
|
css = css.slice(rbracket + 1).trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 返回JSON形式的结果串
|
// 返回JSON形式的结果串
|
||||||
return json;
|
return json
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -184,11 +188,11 @@ export function css2json(css) {
|
|||||||
* @param {*} name
|
* @param {*} name
|
||||||
*/
|
*/
|
||||||
export function saveEditorContent(editor, name) {
|
export function saveEditorContent(editor, name) {
|
||||||
const content = editor.getValue(0);
|
const content = editor.getValue(0)
|
||||||
if (content) {
|
if (content) {
|
||||||
localStorage.setItem(name, content);
|
localStorage.setItem(name, content)
|
||||||
} else {
|
} else {
|
||||||
localStorage.removeItem(name);
|
localStorage.removeItem(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,10 +202,10 @@ export function saveEditorContent(editor, name) {
|
|||||||
*/
|
*/
|
||||||
export function formatDoc(content) {
|
export function formatDoc(content) {
|
||||||
const doc = prettier.format(content, {
|
const doc = prettier.format(content, {
|
||||||
parser: "markdown",
|
parser: `markdown`,
|
||||||
plugins: [prettierMarkdown],
|
plugins: [prettierMarkdown],
|
||||||
});
|
})
|
||||||
return doc;
|
return doc
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -210,10 +214,10 @@ export function formatDoc(content) {
|
|||||||
*/
|
*/
|
||||||
export function formatCss(content) {
|
export function formatCss(content) {
|
||||||
const doc = prettier.format(content, {
|
const doc = prettier.format(content, {
|
||||||
parser: "css",
|
parser: `css`,
|
||||||
plugins: [prettierCss],
|
plugins: [prettierCss],
|
||||||
});
|
})
|
||||||
return doc;
|
return doc
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -221,72 +225,73 @@ export function formatCss(content) {
|
|||||||
* @param {文档内容} doc
|
* @param {文档内容} doc
|
||||||
*/
|
*/
|
||||||
export function downloadMD(doc) {
|
export function downloadMD(doc) {
|
||||||
let downLink = document.createElement("a");
|
let downLink = document.createElement(`a`)
|
||||||
|
|
||||||
downLink.download = "content.md";
|
downLink.download = `content.md`
|
||||||
downLink.style.display = "none";
|
downLink.style.display = `none`
|
||||||
let blob = new Blob([doc]);
|
let blob = new Blob([doc])
|
||||||
|
|
||||||
downLink.href = URL.createObjectURL(blob);
|
downLink.href = URL.createObjectURL(blob)
|
||||||
document.body.appendChild(downLink);
|
document.body.appendChild(downLink)
|
||||||
downLink.click();
|
downLink.click()
|
||||||
document.body.removeChild(downLink);
|
document.body.removeChild(downLink)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出 HTML 生成内容
|
* 导出 HTML 生成内容
|
||||||
*/
|
*/
|
||||||
export function exportHTML() {
|
export function exportHTML() {
|
||||||
const element = document.querySelector("#output");
|
const element = document.querySelector(`#output`)
|
||||||
setStyles(element);
|
setStyles(element)
|
||||||
const htmlStr = element.innerHTML;
|
const htmlStr = element.innerHTML
|
||||||
|
|
||||||
const downLink = document.createElement("a");
|
const downLink = document.createElement(`a`)
|
||||||
|
|
||||||
downLink.download = "content.html";
|
downLink.download = `content.html`
|
||||||
downLink.style.display = "none";
|
downLink.style.display = `none`
|
||||||
let blob = new Blob([
|
let blob = new Blob([
|
||||||
`<html><head><meta charset="utf-8" /></head><body><div style="width: 750px; margin: auto;">${htmlStr}</div></body></html>`,
|
`<html><head><meta charset="utf-8" /></head><body><div style="width: 750px; margin: auto;">${htmlStr}</div></body></html>`,
|
||||||
]);
|
])
|
||||||
|
|
||||||
downLink.href = URL.createObjectURL(blob);
|
downLink.href = URL.createObjectURL(blob)
|
||||||
document.body.appendChild(downLink);
|
document.body.appendChild(downLink)
|
||||||
downLink.click();
|
downLink.click()
|
||||||
document.body.removeChild(downLink);
|
document.body.removeChild(downLink)
|
||||||
|
|
||||||
function setStyles(element) {
|
function setStyles(element) {
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case isPre(element):
|
case isPre(element):
|
||||||
case isCode(element):
|
case isCode(element):
|
||||||
case isSpan(element):
|
case isSpan(element):
|
||||||
element.setAttribute("style", getElementStyles(element));
|
element.setAttribute(`style`, getElementStyles(element))
|
||||||
|
// eslint-disable-next-line no-fallthrough
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
if (element.children.length) {
|
if (element.children.length) {
|
||||||
Array.from(element.children).forEach((child) => setStyles(child));
|
Array.from(element.children).forEach((child) => setStyles(child))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断是否是包裹代码块的 pre 元素
|
// 判断是否是包裹代码块的 pre 元素
|
||||||
function isPre(element) {
|
function isPre(element) {
|
||||||
return (
|
return (
|
||||||
element.tagName === "PRE" &&
|
element.tagName === `PRE` &&
|
||||||
Array.from(element.classList).includes("code__pre")
|
Array.from(element.classList).includes(`code__pre`)
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
// 判断是否是包裹代码块的 code 元素
|
// 判断是否是包裹代码块的 code 元素
|
||||||
function isCode(element) {
|
function isCode(element) {
|
||||||
return (
|
return (
|
||||||
element.tagName === "CODE" &&
|
element.tagName === `CODE` &&
|
||||||
Array.from(element.classList).includes("prettyprint")
|
Array.from(element.classList).includes(`prettyprint`)
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
// 判断是否是包裹代码字符的 span 元素
|
// 判断是否是包裹代码字符的 span 元素
|
||||||
function isSpan(element) {
|
function isSpan(element) {
|
||||||
return (
|
return (
|
||||||
element.tagName === "SPAN" &&
|
element.tagName === `SPAN` &&
|
||||||
(isCode(element.parentElement) ||
|
(isCode(element.parentElement) ||
|
||||||
isCode(element.parentElement.parentElement))
|
isCode(element.parentElement.parentElement))
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -298,52 +303,52 @@ export function exportHTML() {
|
|||||||
* @param {*} cols 列
|
* @param {*} cols 列
|
||||||
*/
|
*/
|
||||||
export function createTable({ data, rows, cols }) {
|
export function createTable({ data, rows, cols }) {
|
||||||
let table = "";
|
let table = ``
|
||||||
let currRow = [];
|
let currRow = []
|
||||||
for (let i = 0; i < rows + 2; ++i) {
|
for (let i = 0; i < rows + 2; ++i) {
|
||||||
table += "|\t";
|
table += `|\t`
|
||||||
currRow = [];
|
currRow = []
|
||||||
for (let j = 0; j < cols; ++j) {
|
for (let j = 0; j < cols; ++j) {
|
||||||
const rowIdx = i > 1 ? i - 1 : i;
|
const rowIdx = i > 1 ? i - 1 : i
|
||||||
i === 1
|
i === 1
|
||||||
? currRow.push("---\t")
|
? currRow.push(`---\t`)
|
||||||
: currRow.push(data[`k_${rowIdx}_${j}`] || "");
|
: currRow.push(data[`k_${rowIdx}_${j}`] || ``)
|
||||||
}
|
}
|
||||||
table += currRow.join("\t|\t");
|
table += currRow.join(`\t|\t`)
|
||||||
table += "\t|\n";
|
table += `\t|\n`
|
||||||
}
|
}
|
||||||
|
|
||||||
return table;
|
return table
|
||||||
}
|
}
|
||||||
|
|
||||||
export const toBase64 = (file) =>
|
export const toBase64 = (file) =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader()
|
||||||
reader.readAsDataURL(file);
|
reader.readAsDataURL(file)
|
||||||
reader.onload = () => resolve(reader.result.split(",").pop());
|
reader.onload = () => resolve(reader.result.split(`,`).pop())
|
||||||
reader.onerror = (error) => reject(error);
|
reader.onerror = (error) => reject(error)
|
||||||
});
|
})
|
||||||
|
|
||||||
export function checkImage(file) {
|
export function checkImage(file) {
|
||||||
// check filename suffix
|
// check filename suffix
|
||||||
const isValidSuffix = /\.(gif|jpg|jpeg|png|GIF|JPG|PNG)$/.test(file.name);
|
const isValidSuffix = /\.(gif|jpg|jpeg|png|GIF|JPG|PNG)$/.test(file.name)
|
||||||
if (!isValidSuffix) {
|
if (!isValidSuffix) {
|
||||||
return {
|
return {
|
||||||
ok: false,
|
ok: false,
|
||||||
msg: "请上传 JPG/PNG/GIF 格式的图片",
|
msg: `请上传 JPG/PNG/GIF 格式的图片`,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check file size
|
// check file size
|
||||||
const maxSize = 10;
|
const maxSize = 10
|
||||||
const valid = file.size / 1024 / 1024 <= maxSize;
|
const valid = file.size / 1024 / 1024 <= maxSize
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
return {
|
return {
|
||||||
ok: false,
|
ok: false,
|
||||||
msg: `由于公众号限制,图片大小不能超过 ${maxSize}M`,
|
msg: `由于公众号限制,图片大小不能超过 ${maxSize}M`,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
return { ok: true };
|
return { ok: true }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -352,12 +357,12 @@ export function checkImage(file) {
|
|||||||
* @param {排除的属性} excludes 如果某些属性对结果有不良影响,可以使用这个参数来排除
|
* @param {排除的属性} excludes 如果某些属性对结果有不良影响,可以使用这个参数来排除
|
||||||
* @returns 行内样式拼接结果
|
* @returns 行内样式拼接结果
|
||||||
*/
|
*/
|
||||||
function getElementStyles(element, excludes = ["width", "height"]) {
|
function getElementStyles(element, excludes = [`width`, `height`]) {
|
||||||
const styles = getComputedStyle(element, null);
|
const styles = getComputedStyle(element, null)
|
||||||
return Object.entries(styles)
|
return Object.entries(styles)
|
||||||
.filter(([key]) => styles.getPropertyValue(key) && !excludes.includes(key))
|
.filter(([key]) => styles.getPropertyValue(key) && !excludes.includes(key))
|
||||||
.map(([key, value]) => `${key}:${value};`)
|
.map(([key, value]) => `${key}:${value};`)
|
||||||
.join("");
|
.join(``)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -366,14 +371,13 @@ function getElementStyles(element, excludes = ["width", "height"]) {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function removeLeft(str) {
|
export function removeLeft(str) {
|
||||||
const lines = str.split('\n')
|
const lines = str.split(`\n`)
|
||||||
// 获取应该删除的空白符数量
|
// 获取应该删除的空白符数量
|
||||||
const minSpaceNum = lines.filter(item => item.trim())
|
const minSpaceNum = lines
|
||||||
.map(item => item.match(/(^\s+)?/)[0].length)
|
.filter((item) => item.trim())
|
||||||
|
.map((item) => item.match(/(^\s+)?/)[0].length)
|
||||||
.sort((a, b) => a - b)[0]
|
.sort((a, b) => a - b)[0]
|
||||||
// 删除空白符
|
// 删除空白符
|
||||||
const newStr = lines
|
const newStr = lines.map((item) => item.slice(minSpaceNum)).join(`\n`)
|
||||||
.map(item => item.slice(minSpaceNum))
|
|
||||||
.join('\n')
|
|
||||||
return newStr
|
return newStr
|
||||||
}
|
}
|
||||||
|
@ -44,10 +44,10 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onRedirect(url) {
|
onRedirect(url) {
|
||||||
window.open(url);
|
window.open(url)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@ -1,22 +1,32 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-container class="top is-dark">
|
<el-container class="top is-dark">
|
||||||
<el-dialog
|
<el-dialog title="发布" :visible.sync="form.dialogVisible">
|
||||||
title="发布"
|
|
||||||
:visible.sync="form.dialogVisible"
|
|
||||||
>
|
|
||||||
<div class="postInfo">
|
<div class="postInfo">
|
||||||
<el-form ref="form" :model="form" label-width="80px">
|
<el-form ref="form" :model="form" label-width="80px">
|
||||||
<el-form-item label="封面">
|
<el-form-item label="封面">
|
||||||
<el-input v-model="form.thumb" placeholder="自动提取第一张图"></el-input>
|
<el-input
|
||||||
|
v-model="form.thumb"
|
||||||
|
placeholder="自动提取第一张图"
|
||||||
|
></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="标题">
|
<el-form-item label="标题">
|
||||||
<el-input v-model="form.title" placeholder="自动提取第一个标题"></el-input>
|
<el-input
|
||||||
|
v-model="form.title"
|
||||||
|
placeholder="自动提取第一个标题"
|
||||||
|
></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="描述">
|
<el-form-item label="描述">
|
||||||
<el-input type="textarea" :rows="4" v-model="form.desc" placeholder="自动提取第一个段落"></el-input>
|
<el-input
|
||||||
|
type="textarea"
|
||||||
|
:rows="4"
|
||||||
|
v-model="form.desc"
|
||||||
|
placeholder="自动提取第一个段落"
|
||||||
|
></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<div class="info">注:此功能由第三方浏览器插件支持,本平台不保证安全性。</div>
|
<div class="info">
|
||||||
|
注:此功能由第三方浏览器插件支持,本平台不保证安全性。
|
||||||
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
@ -238,14 +248,14 @@ import {
|
|||||||
setFontSize,
|
setFontSize,
|
||||||
fixCodeWhiteSpace,
|
fixCodeWhiteSpace,
|
||||||
setColorWithCustomTemplate,
|
setColorWithCustomTemplate,
|
||||||
} from "../../assets/scripts/util";
|
} from '../../assets/scripts/util'
|
||||||
import { solveWeChatImage, solveHtml } from "../../assets/scripts/converter";
|
import { solveWeChatImage, solveHtml } from '../../assets/scripts/converter'
|
||||||
import config from "../../assets/scripts/config";
|
import config from '../../assets/scripts/config'
|
||||||
import DEFAULT_CSS_CONTENT from "@/assets/example/theme-css.txt";
|
import DEFAULT_CSS_CONTENT from '@/assets/example/theme-css.txt'
|
||||||
import resetDialog from "./resetDialog";
|
import resetDialog from './resetDialog'
|
||||||
import { mapState, mapMutations } from "vuex";
|
import { mapState, mapMutations } from 'vuex'
|
||||||
export default {
|
export default {
|
||||||
name: "editor-header",
|
name: `editor-header`,
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
form: {
|
form: {
|
||||||
@ -258,24 +268,24 @@ export default {
|
|||||||
config: config,
|
config: config,
|
||||||
citeStatus: false,
|
citeStatus: false,
|
||||||
showResetConfirm: false,
|
showResetConfirm: false,
|
||||||
selectFont: "",
|
selectFont: ``,
|
||||||
selectSize: "",
|
selectSize: ``,
|
||||||
selectColor: "",
|
selectColor: ``,
|
||||||
selectCodeTheme: config.codeThemeOption[0].value
|
selectCodeTheme: config.codeThemeOption[0].value,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
resetDialog,
|
resetDialog,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
effect() {
|
effect() {
|
||||||
return this.nightMode ? "dark" : "light";
|
return this.nightMode ? `dark` : `light`
|
||||||
},
|
},
|
||||||
btnContent() {
|
btnContent() {
|
||||||
return this.nightMode ? "浅色模式" : "暗黑模式";
|
return this.nightMode ? `浅色模式` : `暗黑模式`
|
||||||
},
|
},
|
||||||
btnType() {
|
btnType() {
|
||||||
return this.nightMode ? "default" : "primary";
|
return this.nightMode ? `default` : `primary`
|
||||||
},
|
},
|
||||||
...mapState({
|
...mapState({
|
||||||
output: (state) => state.output,
|
output: (state) => state.output,
|
||||||
@ -295,7 +305,9 @@ export default {
|
|||||||
try {
|
try {
|
||||||
auto = {
|
auto = {
|
||||||
thumb: document.querySelector(`#output img`).src,
|
thumb: document.querySelector(`#output img`).src,
|
||||||
title: [1,2,3,4,5,6].map(h => document.querySelector(`#output h${h}`)).filter(h => h)[0].innerText,
|
title: [1, 2, 3, 4, 5, 6]
|
||||||
|
.map((h) => document.querySelector(`#output h${h}`))
|
||||||
|
.filter((h) => h)[0].innerText,
|
||||||
desc: document.querySelector(`#output p`).innerText,
|
desc: document.querySelector(`#output p`).innerText,
|
||||||
content: this.output,
|
content: this.output,
|
||||||
}
|
}
|
||||||
@ -321,124 +333,124 @@ export default {
|
|||||||
fontChanged(fonts) {
|
fontChanged(fonts) {
|
||||||
this.setWxRendererOptions({
|
this.setWxRendererOptions({
|
||||||
fonts: fonts,
|
fonts: fonts,
|
||||||
});
|
})
|
||||||
this.setCurrentFont(fonts);
|
this.setCurrentFont(fonts)
|
||||||
this.$emit("refresh");
|
this.$emit(`refresh`)
|
||||||
},
|
},
|
||||||
sizeChanged(size) {
|
sizeChanged(size) {
|
||||||
let theme = setFontSize(size.replace("px", ""));
|
let theme = setFontSize(size.replace(`px`, ``))
|
||||||
theme = setColorWithCustomTemplate(theme, this.currentColor);
|
theme = setColorWithCustomTemplate(theme, this.currentColor)
|
||||||
this.setWxRendererOptions({
|
this.setWxRendererOptions({
|
||||||
size: size,
|
size: size,
|
||||||
theme: theme,
|
theme: theme,
|
||||||
});
|
})
|
||||||
this.setCurrentSize(size);
|
this.setCurrentSize(size)
|
||||||
this.$emit("refresh");
|
this.$emit(`refresh`)
|
||||||
},
|
},
|
||||||
colorChanged(color) {
|
colorChanged(color) {
|
||||||
let theme = setFontSize(this.currentSize.replace("px", ""));
|
let theme = setFontSize(this.currentSize.replace(`px`, ``))
|
||||||
|
|
||||||
theme = setColorWithCustomTemplate(theme, color);
|
theme = setColorWithCustomTemplate(theme, color)
|
||||||
this.setWxRendererOptions({
|
this.setWxRendererOptions({
|
||||||
theme: theme,
|
theme: theme,
|
||||||
});
|
})
|
||||||
this.setCurrentColor(color);
|
this.setCurrentColor(color)
|
||||||
this.$emit("refresh");
|
this.$emit(`refresh`)
|
||||||
},
|
},
|
||||||
codeThemeChanged(theme) {
|
codeThemeChanged(theme) {
|
||||||
this.setCurrentCodeTheme(theme);
|
this.setCurrentCodeTheme(theme)
|
||||||
this.$emit("refresh");
|
this.$emit(`refresh`)
|
||||||
},
|
},
|
||||||
statusChanged(val) {
|
statusChanged(val) {
|
||||||
this.setCiteStatus(val);
|
this.setCiteStatus(val)
|
||||||
this.$emit("refresh");
|
this.$emit(`refresh`)
|
||||||
},
|
},
|
||||||
// 复制到微信公众号
|
// 复制到微信公众号
|
||||||
copy(e) {
|
copy(e) {
|
||||||
this.$emit("startCopy");
|
this.$emit(`startCopy`)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
let clipboardDiv = document.getElementById("output");
|
let clipboardDiv = document.getElementById(`output`)
|
||||||
solveWeChatImage();
|
solveWeChatImage()
|
||||||
solveHtml();
|
solveHtml()
|
||||||
clipboardDiv.focus();
|
clipboardDiv.focus()
|
||||||
window.getSelection().removeAllRanges();
|
window.getSelection().removeAllRanges()
|
||||||
let range = document.createRange();
|
let range = document.createRange()
|
||||||
|
|
||||||
range.setStartBefore(clipboardDiv.firstChild);
|
range.setStartBefore(clipboardDiv.firstChild)
|
||||||
range.setEndAfter(clipboardDiv.lastChild);
|
range.setEndAfter(clipboardDiv.lastChild)
|
||||||
window.getSelection().addRange(range);
|
window.getSelection().addRange(range)
|
||||||
document.execCommand("copy");
|
document.execCommand(`copy`)
|
||||||
window.getSelection().removeAllRanges();
|
window.getSelection().removeAllRanges()
|
||||||
clipboardDiv.innerHTML = this.output;
|
clipboardDiv.innerHTML = this.output
|
||||||
// 输出提示
|
// 输出提示
|
||||||
this.$notify({
|
this.$notify({
|
||||||
showClose: true,
|
showClose: true,
|
||||||
message: "已复制渲染后的文章到剪贴板,可直接到公众号后台粘贴",
|
message: `已复制渲染后的文章到剪贴板,可直接到公众号后台粘贴`,
|
||||||
offset: 80,
|
offset: 80,
|
||||||
duration: 1600,
|
duration: 1600,
|
||||||
type: "success",
|
type: `success`,
|
||||||
});
|
})
|
||||||
this.$emit("refresh");
|
this.$emit(`refresh`)
|
||||||
this.$emit("endCopy");
|
this.$emit(`endCopy`)
|
||||||
}, 350);
|
}, 350)
|
||||||
},
|
},
|
||||||
// 自定义CSS样式
|
// 自定义CSS样式
|
||||||
async customStyle() {
|
async customStyle() {
|
||||||
this.$emit("showCssEditor");
|
this.$emit(`showCssEditor`)
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
if (!this.cssEditor) {
|
if (!this.cssEditor) {
|
||||||
this.cssEditor.refresh();
|
this.cssEditor.refresh()
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.cssEditor.refresh();
|
this.cssEditor.refresh()
|
||||||
}, 50);
|
}, 50)
|
||||||
|
|
||||||
let flag = await localStorage.getItem("__css_content");
|
let flag = await localStorage.getItem(`__css_content`)
|
||||||
if (!flag) {
|
if (!flag) {
|
||||||
this.setCssEditorValue(DEFAULT_CSS_CONTENT);
|
this.setCssEditorValue(DEFAULT_CSS_CONTENT)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 重置样式
|
// 重置样式
|
||||||
confirmReset() {
|
confirmReset() {
|
||||||
localStorage.clear();
|
localStorage.clear()
|
||||||
this.cssEditor.setValue(DEFAULT_CSS_CONTENT);
|
this.cssEditor.setValue(DEFAULT_CSS_CONTENT)
|
||||||
this.citeStatus = false;
|
this.citeStatus = false
|
||||||
this.statusChanged(false);
|
this.statusChanged(false)
|
||||||
this.fontChanged(this.config.builtinFonts[0].value);
|
this.fontChanged(this.config.builtinFonts[0].value)
|
||||||
this.colorChanged(this.config.colorOption[0].value);
|
this.colorChanged(this.config.colorOption[0].value)
|
||||||
this.sizeChanged(this.config.sizeOption[2].value);
|
this.sizeChanged(this.config.sizeOption[2].value)
|
||||||
this.codeThemeChanged(this.config.codeThemeOption[0].value)
|
this.codeThemeChanged(this.config.codeThemeOption[0].value)
|
||||||
this.$emit("cssChanged");
|
this.$emit(`cssChanged`)
|
||||||
this.selectFont = this.currentFont;
|
this.selectFont = this.currentFont
|
||||||
this.selectSize = this.currentSize;
|
this.selectSize = this.currentSize
|
||||||
this.selectColor = this.currentColor;
|
this.selectColor = this.currentColor
|
||||||
this.showResetConfirm = false;
|
this.showResetConfirm = false
|
||||||
this.selectCodeTheme = this.codeTheme;
|
this.selectCodeTheme = this.codeTheme
|
||||||
},
|
},
|
||||||
cancelReset() {
|
cancelReset() {
|
||||||
this.showResetConfirm = false;
|
this.showResetConfirm = false
|
||||||
this.editor.focus();
|
this.editor.focus()
|
||||||
},
|
},
|
||||||
...mapMutations([
|
...mapMutations([
|
||||||
"setCurrentColor",
|
`setCurrentColor`,
|
||||||
"setCiteStatus",
|
`setCiteStatus`,
|
||||||
"themeChanged",
|
`themeChanged`,
|
||||||
"setCurrentFont",
|
`setCurrentFont`,
|
||||||
"setCurrentSize",
|
`setCurrentSize`,
|
||||||
"setCssEditorValue",
|
`setCssEditorValue`,
|
||||||
"setCurrentCodeTheme",
|
`setCurrentCodeTheme`,
|
||||||
"setWxRendererOptions",
|
`setWxRendererOptions`,
|
||||||
]),
|
]),
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.selectFont = this.currentFont;
|
this.selectFont = this.currentFont
|
||||||
this.selectSize = this.currentSize;
|
this.selectSize = this.currentSize
|
||||||
this.selectColor = this.currentColor;
|
this.selectColor = this.currentColor
|
||||||
this.selectCodeTheme = this.codeTheme;
|
this.selectCodeTheme = this.codeTheme
|
||||||
this.citeStatus = this.currentCiteStatus;
|
this.citeStatus = this.currentCiteStatus
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@ -459,12 +471,12 @@ export default {
|
|||||||
margin-right: 24px;
|
margin-right: 24px;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
background: url("../../assets/images/night.png") no-repeat;
|
background: url('../../assets/images/night.png') no-repeat;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
}
|
}
|
||||||
.mode__switch_black {
|
.mode__switch_black {
|
||||||
background: url("../../assets/images/light.png") no-repeat;
|
background: url('../../assets/images/light.png') no-repeat;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
}
|
}
|
||||||
.top {
|
.top {
|
||||||
|
@ -53,9 +53,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import config from "../../assets/scripts/config";
|
import config from '../../assets/scripts/config'
|
||||||
import { createTable } from "../../assets/scripts/util";
|
import { createTable } from '../../assets/scripts/util'
|
||||||
import { mapState, mapMutations } from "vuex";
|
import { mapState, mapMutations } from 'vuex'
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
@ -69,11 +69,11 @@ export default {
|
|||||||
rowNum: 3,
|
rowNum: 3,
|
||||||
colNum: 3,
|
colNum: 3,
|
||||||
tableData: {},
|
tableData: {},
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
btnType() {
|
btnType() {
|
||||||
return this.nightMode ? "default" : "primary";
|
return this.nightMode ? `default` : `primary`
|
||||||
},
|
},
|
||||||
...mapState({
|
...mapState({
|
||||||
nightMode: (state) => state.nightMode,
|
nightMode: (state) => state.nightMode,
|
||||||
@ -83,23 +83,23 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
// 插入表格
|
// 插入表格
|
||||||
insertTable() {
|
insertTable() {
|
||||||
const cursor = this.editor.getCursor();
|
const cursor = this.editor.getCursor()
|
||||||
const table = createTable({
|
const table = createTable({
|
||||||
data: this.tableData,
|
data: this.tableData,
|
||||||
rows: this.rowNum,
|
rows: this.rowNum,
|
||||||
cols: this.colNum,
|
cols: this.colNum,
|
||||||
});
|
})
|
||||||
|
|
||||||
this.tableData = {};
|
this.tableData = {}
|
||||||
this.rowNum = 3;
|
this.rowNum = 3
|
||||||
this.colNum = 3;
|
this.colNum = 3
|
||||||
this.editor.replaceSelection(`\n${table}\n`, "end");
|
this.editor.replaceSelection(`\n${table}\n`, `end`)
|
||||||
this.$emit("input", false);
|
this.$emit(`input`, false)
|
||||||
this.editorRefresh();
|
this.editorRefresh()
|
||||||
},
|
},
|
||||||
...mapMutations(["editorRefresh"]),
|
...mapMutations([`editorRefresh`]),
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapState } from "vuex";
|
import { mapState } from 'vuex'
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
showResetConfirm: {
|
showResetConfirm: {
|
||||||
@ -26,13 +26,13 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
btnType() {
|
btnType() {
|
||||||
return this.nightMode ? "default" : "primary";
|
return this.nightMode ? `default` : `primary`
|
||||||
},
|
},
|
||||||
...mapState({
|
...mapState({
|
||||||
nightMode: (state) => state.nightMode,
|
nightMode: (state) => state.nightMode,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@ -39,49 +39,49 @@ export default {
|
|||||||
menu: [
|
menu: [
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
text: "上传图片",
|
text: `上传图片`,
|
||||||
key: "insertPic",
|
key: `insertPic`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "插入表格",
|
text: `插入表格`,
|
||||||
key: "insertTable",
|
key: `insertTable`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "恢复默认样式",
|
text: `恢复默认样式`,
|
||||||
key: "resetStyle",
|
key: `resetStyle`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
text: '导入 Markdown 文档',
|
text: `导入 Markdown 文档`,
|
||||||
key: 'importMarkdown',
|
key: `importMarkdown`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "导出 Markdown 文档",
|
text: `导出 Markdown 文档`,
|
||||||
key: "download",
|
key: `download`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "导出 HTML 页面",
|
text: `导出 HTML 页面`,
|
||||||
key: "export",
|
key: `export`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "格式化 Markdown 文档",
|
text: `格式化 Markdown 文档`,
|
||||||
key: "formatMarkdown",
|
key: `formatMarkdown`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
closeCB() {
|
closeCB() {
|
||||||
this.$emit("input", false);
|
this.$emit(`input`, false)
|
||||||
},
|
},
|
||||||
onMouseDown(key) {
|
onMouseDown(key) {
|
||||||
this.$emit("menuTick", key);
|
this.$emit(`menuTick`, key)
|
||||||
this.$emit("closeMenu", false);
|
this.$emit(`closeMenu`, false)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@ -386,8 +386,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { checkImage, removeLeft } from "../../assets/scripts/util";
|
import { checkImage, removeLeft } from '../../assets/scripts/util'
|
||||||
import CodeMirror from "codemirror/lib/codemirror";
|
import CodeMirror from 'codemirror/lib/codemirror'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@ -401,45 +401,45 @@ export default {
|
|||||||
activeName: `upload`,
|
activeName: `upload`,
|
||||||
|
|
||||||
formGitHub: {
|
formGitHub: {
|
||||||
repo: "",
|
repo: ``,
|
||||||
branch: "",
|
branch: ``,
|
||||||
accessToken: "",
|
accessToken: ``,
|
||||||
},
|
},
|
||||||
formGitee: {
|
formGitee: {
|
||||||
repo: "",
|
repo: ``,
|
||||||
branch: "",
|
branch: ``,
|
||||||
accessToken: "",
|
accessToken: ``,
|
||||||
},
|
},
|
||||||
formAliOSS: {
|
formAliOSS: {
|
||||||
accessKeyId: "",
|
accessKeyId: ``,
|
||||||
accessKeySecret: "",
|
accessKeySecret: ``,
|
||||||
bucket: "",
|
bucket: ``,
|
||||||
region: "",
|
region: ``,
|
||||||
path: "",
|
path: ``,
|
||||||
cdnHost: "",
|
cdnHost: ``,
|
||||||
},
|
},
|
||||||
minioOSS: {
|
minioOSS: {
|
||||||
endpoint: "",
|
endpoint: ``,
|
||||||
port: "",
|
port: ``,
|
||||||
useSSL: true,
|
useSSL: true,
|
||||||
bucket: "",
|
bucket: ``,
|
||||||
accessKey: "",
|
accessKey: ``,
|
||||||
secretKey: "",
|
secretKey: ``,
|
||||||
},
|
},
|
||||||
formTxCOS: {
|
formTxCOS: {
|
||||||
secretId: "",
|
secretId: ``,
|
||||||
secretKey: "",
|
secretKey: ``,
|
||||||
bucket: "",
|
bucket: ``,
|
||||||
region: "",
|
region: ``,
|
||||||
path: "",
|
path: ``,
|
||||||
cdnHost: "",
|
cdnHost: ``,
|
||||||
},
|
},
|
||||||
formQiniu: {
|
formQiniu: {
|
||||||
accessKey: "",
|
accessKey: ``,
|
||||||
secretKey: "",
|
secretKey: ``,
|
||||||
bucket: "",
|
bucket: ``,
|
||||||
domain: "",
|
domain: ``,
|
||||||
region: "",
|
region: ``,
|
||||||
},
|
},
|
||||||
formCustom: {
|
formCustom: {
|
||||||
code:
|
code:
|
||||||
@ -460,83 +460,83 @@ export default {
|
|||||||
},
|
},
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
value: "default",
|
value: `default`,
|
||||||
label: "默认",
|
label: `默认`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "gitee",
|
value: `gitee`,
|
||||||
label: "Gitee",
|
label: `Gitee`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "github",
|
value: `github`,
|
||||||
label: "GitHub",
|
label: `GitHub`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "aliOSS",
|
value: `aliOSS`,
|
||||||
label: "阿里云",
|
label: `阿里云`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "txCOS",
|
value: `txCOS`,
|
||||||
label: "腾讯云",
|
label: `腾讯云`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "qiniu",
|
value: `qiniu`,
|
||||||
label: "七牛云",
|
label: `七牛云`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "minio",
|
value: `minio`,
|
||||||
label: "MinIO",
|
label: `MinIO`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "formCustom",
|
value: `formCustom`,
|
||||||
label: "自定义代码",
|
label: `自定义代码`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
imgHost: "default",
|
imgHost: `default`,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
if (localStorage.getItem("githubConfig")) {
|
if (localStorage.getItem(`githubConfig`)) {
|
||||||
this.formGitHub = JSON.parse(localStorage.getItem("githubConfig"));
|
this.formGitHub = JSON.parse(localStorage.getItem(`githubConfig`))
|
||||||
}
|
}
|
||||||
if (localStorage.getItem("giteeConfig")) {
|
if (localStorage.getItem(`giteeConfig`)) {
|
||||||
this.formGitee = JSON.parse(localStorage.getItem("giteeConfig"));
|
this.formGitee = JSON.parse(localStorage.getItem(`giteeConfig`))
|
||||||
}
|
}
|
||||||
if (localStorage.getItem("aliOSSConfig")) {
|
if (localStorage.getItem(`aliOSSConfig`)) {
|
||||||
this.formAliOSS = JSON.parse(localStorage.getItem("aliOSSConfig"));
|
this.formAliOSS = JSON.parse(localStorage.getItem(`aliOSSConfig`))
|
||||||
}
|
}
|
||||||
if (localStorage.getItem("minioConfig")) {
|
if (localStorage.getItem(`minioConfig`)) {
|
||||||
this.minioOSS = JSON.parse(localStorage.getItem("minioConfig"));
|
this.minioOSS = JSON.parse(localStorage.getItem(`minioConfig`))
|
||||||
}
|
}
|
||||||
if (localStorage.getItem("txCOSConfig")) {
|
if (localStorage.getItem(`txCOSConfig`)) {
|
||||||
this.formTxCOS = JSON.parse(localStorage.getItem("txCOSConfig"));
|
this.formTxCOS = JSON.parse(localStorage.getItem(`txCOSConfig`))
|
||||||
}
|
}
|
||||||
if (localStorage.getItem("imgHost")) {
|
if (localStorage.getItem(`imgHost`)) {
|
||||||
this.imgHost = localStorage.getItem("imgHost");
|
this.imgHost = localStorage.getItem(`imgHost`)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
changeImgHost() {
|
changeImgHost() {
|
||||||
localStorage.setItem("imgHost", this.imgHost);
|
localStorage.setItem(`imgHost`, this.imgHost)
|
||||||
this.$message.success("已成功切换图床");
|
this.$message.success(`已成功切换图床`)
|
||||||
},
|
},
|
||||||
saveGitHubConfiguration() {
|
saveGitHubConfiguration() {
|
||||||
if (!(this.formGitHub.repo && this.formGitHub.accessToken)) {
|
if (!(this.formGitHub.repo && this.formGitHub.accessToken)) {
|
||||||
const blankElement = this.formGitHub.repo ? "token" : "GitHub 仓库";
|
const blankElement = this.formGitHub.repo ? `token` : `GitHub 仓库`
|
||||||
this.$message.error(`参数「${blankElement}」不能为空`);
|
this.$message.error(`参数「${blankElement}」不能为空`)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
localStorage.setItem("githubConfig", JSON.stringify(this.formGitHub));
|
localStorage.setItem(`githubConfig`, JSON.stringify(this.formGitHub))
|
||||||
this.$message.success("保存成功");
|
this.$message.success(`保存成功`)
|
||||||
},
|
},
|
||||||
saveGiteeConfiguration() {
|
saveGiteeConfiguration() {
|
||||||
if (!(this.formGitee.repo && this.formGitee.accessToken)) {
|
if (!(this.formGitee.repo && this.formGitee.accessToken)) {
|
||||||
const blankElement = this.formGitee.repo ? "私人令牌" : "Gitee 仓库";
|
const blankElement = this.formGitee.repo ? `私人令牌` : `Gitee 仓库`
|
||||||
this.$message.error(`参数「${blankElement}」不能为空`);
|
this.$message.error(`参数「${blankElement}」不能为空`)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
localStorage.setItem("giteeConfig", JSON.stringify(this.formGitee));
|
localStorage.setItem(`giteeConfig`, JSON.stringify(this.formGitee))
|
||||||
this.$message.success("保存成功");
|
this.$message.success(`保存成功`)
|
||||||
},
|
},
|
||||||
saveAliOSSConfiguration() {
|
saveAliOSSConfiguration() {
|
||||||
if (
|
if (
|
||||||
@ -547,11 +547,11 @@ export default {
|
|||||||
this.formAliOSS.region
|
this.formAliOSS.region
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
this.$message.error(`阿里云 OSS 参数配置不全`);
|
this.$message.error(`阿里云 OSS 参数配置不全`)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
localStorage.setItem("aliOSSConfig", JSON.stringify(this.formAliOSS));
|
localStorage.setItem(`aliOSSConfig`, JSON.stringify(this.formAliOSS))
|
||||||
this.$message.success("保存成功");
|
this.$message.success(`保存成功`)
|
||||||
},
|
},
|
||||||
saveMinioOSSConfiguration() {
|
saveMinioOSSConfiguration() {
|
||||||
if (
|
if (
|
||||||
@ -562,11 +562,11 @@ export default {
|
|||||||
this.minioOSS.secretKey
|
this.minioOSS.secretKey
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
this.$message.error(`MinIO 参数配置不全`);
|
this.$message.error(`MinIO 参数配置不全`)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
localStorage.setItem("minioConfig", JSON.stringify(this.minioOSS));
|
localStorage.setItem(`minioConfig`, JSON.stringify(this.minioOSS))
|
||||||
this.$message.success("保存成功");
|
this.$message.success(`保存成功`)
|
||||||
},
|
},
|
||||||
saveTxCOSConfiguration() {
|
saveTxCOSConfiguration() {
|
||||||
if (
|
if (
|
||||||
@ -577,11 +577,11 @@ export default {
|
|||||||
this.formTxCOS.region
|
this.formTxCOS.region
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
this.$message.error(`腾讯云 COS 参数配置不全`);
|
this.$message.error(`腾讯云 COS 参数配置不全`)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
localStorage.setItem("txCOSConfig", JSON.stringify(this.formTxCOS));
|
localStorage.setItem(`txCOSConfig`, JSON.stringify(this.formTxCOS))
|
||||||
this.$message.success("保存成功");
|
this.$message.success(`保存成功`)
|
||||||
},
|
},
|
||||||
|
|
||||||
saveQiniuConfiguration() {
|
saveQiniuConfiguration() {
|
||||||
@ -594,40 +594,40 @@ export default {
|
|||||||
this.formQiniu.region
|
this.formQiniu.region
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
this.$message.error(`七牛云 Kodo 参数配置不全`);
|
this.$message.error(`七牛云 Kodo 参数配置不全`)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
localStorage.setItem("qiniuConfig", JSON.stringify(this.formQiniu));
|
localStorage.setItem(`qiniuConfig`, JSON.stringify(this.formQiniu))
|
||||||
this.$message.success("保存成功");
|
this.$message.success(`保存成功`)
|
||||||
},
|
},
|
||||||
formCustomSave() {
|
formCustomSave() {
|
||||||
const str = this.formCustom.editor.getValue();
|
const str = this.formCustom.editor.getValue()
|
||||||
localStorage.setItem(`formCustomConfig`, str);
|
localStorage.setItem(`formCustomConfig`, str)
|
||||||
this.$message.success(`保存成功`);
|
this.$message.success(`保存成功`)
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeImageUpload(file) {
|
beforeImageUpload(file) {
|
||||||
// check image
|
// check image
|
||||||
const checkResult = checkImage(file);
|
const checkResult = checkImage(file)
|
||||||
if (!checkResult.ok) {
|
if (!checkResult.ok) {
|
||||||
this.$message.error(checkResult.msg);
|
this.$message.error(checkResult.msg)
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
// check image host
|
// check image host
|
||||||
let imgHost = localStorage.getItem("imgHost");
|
let imgHost = localStorage.getItem(`imgHost`)
|
||||||
imgHost = imgHost ? imgHost : "default";
|
imgHost = imgHost ? imgHost : `default`
|
||||||
localStorage.setItem("imgHost", imgHost);
|
localStorage.setItem(`imgHost`, imgHost)
|
||||||
|
|
||||||
const config = localStorage.getItem(`${imgHost}Config`);
|
const config = localStorage.getItem(`${imgHost}Config`)
|
||||||
const isValidHost = imgHost == "default" || config;
|
const isValidHost = imgHost == `default` || config
|
||||||
if (!isValidHost) {
|
if (!isValidHost) {
|
||||||
this.$message.error(`请先配置 ${imgHost} 图床参数`);
|
this.$message.error(`请先配置 ${imgHost} 图床参数`)
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
return true;
|
return true
|
||||||
},
|
},
|
||||||
uploadImage(params) {
|
uploadImage(params) {
|
||||||
this.$emit("uploadImage", params.file);
|
this.$emit(`uploadImage`, params.file)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@ -637,20 +637,20 @@ export default {
|
|||||||
if (val === `formCustom`) {
|
if (val === `formCustom`) {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
const textarea =
|
const textarea =
|
||||||
this.$refs.formCustomElInput.$el.querySelector(`textarea`);
|
this.$refs.formCustomElInput.$el.querySelector(`textarea`)
|
||||||
this.formCustom.editor =
|
this.formCustom.editor =
|
||||||
this.formCustom.editor ||
|
this.formCustom.editor ||
|
||||||
CodeMirror.fromTextArea(textarea, {
|
CodeMirror.fromTextArea(textarea, {
|
||||||
mode: `javascript`,
|
mode: `javascript`,
|
||||||
});
|
})
|
||||||
this.formCustom.editor.setValue(this.formCustom.code);
|
this.formCustom.editor.setValue(this.formCustom.code)
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {},
|
mounted() {},
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@ -696,8 +696,8 @@ export default {
|
|||||||
/deep/ .CodeMirror {
|
/deep/ .CodeMirror {
|
||||||
border: 1px solid #eee;
|
border: 1px solid #eee;
|
||||||
height: 300px !important;
|
height: 300px !important;
|
||||||
font-family: "Fira Mono", "DejaVu Sans Mono", Menlo, Consolas,
|
font-family: 'Fira Mono', 'DejaVu Sans Mono', Menlo, Consolas,
|
||||||
"Liberation Mono", Monaco, "Lucida Console", monospace !important;
|
'Liberation Mono', Monaco, 'Lucida Console', monospace !important;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
.CodeMirror-scroll {
|
.CodeMirror-scroll {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 100px;
|
width: 100px;
|
||||||
height: 100px;
|
height: 100px;
|
||||||
background: url("../assets/images/favicon.png") no-repeat;
|
background: url('../assets/images/favicon.png') no-repeat;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
42
src/main.js
42
src/main.js
@ -1,29 +1,29 @@
|
|||||||
import Vue from "vue";
|
import Vue from 'vue'
|
||||||
import App from "./App";
|
import App from './App'
|
||||||
import store from "./store";
|
import store from './store'
|
||||||
import ElementUI from "element-ui";
|
import ElementUI from 'element-ui'
|
||||||
import "element-ui/lib/theme-chalk/index.css";
|
import 'element-ui/lib/theme-chalk/index.css'
|
||||||
import "./plugins/element";
|
import './plugins/element'
|
||||||
import "codemirror/lib/codemirror.css";
|
import 'codemirror/lib/codemirror.css'
|
||||||
import "codemirror/theme/xq-light.css";
|
import 'codemirror/theme/xq-light.css'
|
||||||
import "codemirror/mode/css/css";
|
import 'codemirror/mode/css/css'
|
||||||
import "codemirror/mode/markdown/markdown";
|
import 'codemirror/mode/markdown/markdown'
|
||||||
import "codemirror/addon/edit/closebrackets";
|
import 'codemirror/addon/edit/closebrackets'
|
||||||
import "codemirror/addon/edit/matchbrackets";
|
import 'codemirror/addon/edit/matchbrackets'
|
||||||
import "codemirror/addon/selection/active-line";
|
import 'codemirror/addon/selection/active-line'
|
||||||
import "codemirror/addon/hint/show-hint.js";
|
import 'codemirror/addon/hint/show-hint.js'
|
||||||
import "codemirror/addon/hint/css-hint.js";
|
import 'codemirror/addon/hint/css-hint.js'
|
||||||
import router from './router';
|
import router from './router'
|
||||||
|
|
||||||
Vue.use(ElementUI);
|
Vue.use(ElementUI)
|
||||||
|
|
||||||
Vue.config.productionTip = false;
|
Vue.config.productionTip = false
|
||||||
|
|
||||||
App.mpType = "app";
|
App.mpType = `app`
|
||||||
|
|
||||||
const app = new Vue({
|
const app = new Vue({
|
||||||
router,
|
router,
|
||||||
store,
|
store,
|
||||||
...App,
|
...App,
|
||||||
});
|
})
|
||||||
app.$mount("#app");
|
app.$mount(`#app`)
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Loading from "../../components/Loading";
|
import Loading from '../../components/Loading'
|
||||||
import CodemirrorEditor from "./view/CodemirrorEditor";
|
import CodemirrorEditor from './view/CodemirrorEditor'
|
||||||
export default {
|
export default {
|
||||||
name: "App",
|
name: `App`,
|
||||||
components: {
|
components: {
|
||||||
Loading,
|
Loading,
|
||||||
CodemirrorEditor,
|
CodemirrorEditor,
|
||||||
@ -17,14 +17,14 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: true,
|
loading: true,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.loading = false;
|
this.loading = false
|
||||||
}, 100);
|
}, 100)
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
@show-about-dialog="aboutDialogVisible = true"
|
@show-about-dialog="aboutDialogVisible = true"
|
||||||
@show-dialog-form="dialogFormVisible = true"
|
@show-dialog-form="dialogFormVisible = true"
|
||||||
@show-dialog-upload-img="dialogUploadImgVisible = true"
|
@show-dialog-upload-img="dialogUploadImgVisible = true"
|
||||||
@startCopy="(isCoping = true), (backLight = true)"
|
@startCopy=";(isCoping = true), (backLight = true)"
|
||||||
@endCopy="endCopy"
|
@endCopy="endCopy"
|
||||||
/>
|
/>
|
||||||
</el-header>
|
</el-header>
|
||||||
@ -93,11 +93,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import editorHeader from "../../../components/CodemirrorEditor/header";
|
import editorHeader from '../../../components/CodemirrorEditor/header'
|
||||||
import aboutDialog from "../../../components/CodemirrorEditor/aboutDialog";
|
import aboutDialog from '../../../components/CodemirrorEditor/aboutDialog'
|
||||||
import insertFormDialog from "../../../components/CodemirrorEditor/insertForm";
|
import insertFormDialog from '../../../components/CodemirrorEditor/insertForm'
|
||||||
import rightClickMenu from "../../../components/CodemirrorEditor/rightClickMenu";
|
import rightClickMenu from '../../../components/CodemirrorEditor/rightClickMenu'
|
||||||
import uploadImgDialog from "../../../components/CodemirrorEditor/uploadImgDialog";
|
import uploadImgDialog from '../../../components/CodemirrorEditor/uploadImgDialog'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
css2json,
|
css2json,
|
||||||
@ -108,13 +108,13 @@ import {
|
|||||||
saveEditorContent,
|
saveEditorContent,
|
||||||
customCssWithTemplate,
|
customCssWithTemplate,
|
||||||
checkImage,
|
checkImage,
|
||||||
} from "../../../assets/scripts/util";
|
} from '../../../assets/scripts/util'
|
||||||
|
|
||||||
import { toBase64 } from "../../../assets/scripts/util";
|
import { toBase64 } from '../../../assets/scripts/util'
|
||||||
import fileApi from "../../../api/file";
|
import fileApi from '../../../api/file'
|
||||||
|
|
||||||
require("codemirror/mode/javascript/javascript");
|
require(`codemirror/mode/javascript/javascript`)
|
||||||
import { mapState, mapMutations } from "vuex";
|
import { mapState, mapMutations } from 'vuex'
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -127,10 +127,10 @@ export default {
|
|||||||
backLight: false,
|
backLight: false,
|
||||||
timeout: null,
|
timeout: null,
|
||||||
changeTimer: null,
|
changeTimer: null,
|
||||||
source: "",
|
source: ``,
|
||||||
mouseLeft: 0,
|
mouseLeft: 0,
|
||||||
mouseTop: 0,
|
mouseTop: 0,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
editorHeader,
|
editorHeader,
|
||||||
@ -153,304 +153,304 @@ export default {
|
|||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.initEditorState();
|
this.initEditorState()
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.initEditor();
|
this.initEditor()
|
||||||
this.initCssEditor();
|
this.initCssEditor()
|
||||||
this.onEditorRefresh();
|
this.onEditorRefresh()
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initEditor() {
|
initEditor() {
|
||||||
this.initEditorEntity();
|
this.initEditorEntity()
|
||||||
this.editor.on("change", (cm, e) => {
|
this.editor.on(`change`, (cm, e) => {
|
||||||
if (this.changeTimer) clearTimeout(this.changeTimer);
|
if (this.changeTimer) clearTimeout(this.changeTimer)
|
||||||
this.changeTimer = setTimeout(() => {
|
this.changeTimer = setTimeout(() => {
|
||||||
this.onEditorRefresh();
|
this.onEditorRefresh()
|
||||||
saveEditorContent(this.editor, "__editor_content");
|
saveEditorContent(this.editor, `__editor_content`)
|
||||||
}, 300);
|
}, 300)
|
||||||
});
|
})
|
||||||
|
|
||||||
// 粘贴上传图片并插入
|
// 粘贴上传图片并插入
|
||||||
this.editor.on("paste", (cm, e) => {
|
this.editor.on(`paste`, (cm, e) => {
|
||||||
if (!(e.clipboardData && e.clipboardData.items) || this.isImgLoading) {
|
if (!(e.clipboardData && e.clipboardData.items) || this.isImgLoading) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
for (let i = 0, len = e.clipboardData.items.length; i < len; ++i) {
|
for (let i = 0, len = e.clipboardData.items.length; i < len; ++i) {
|
||||||
let item = e.clipboardData.items[i];
|
let item = e.clipboardData.items[i]
|
||||||
if (item.kind === "file") {
|
if (item.kind === `file`) {
|
||||||
// 校验图床参数
|
// 校验图床参数
|
||||||
const pasteFile = item.getAsFile();
|
const pasteFile = item.getAsFile()
|
||||||
const isValid = this.beforeUpload(pasteFile);
|
const isValid = this.beforeUpload(pasteFile)
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
this.uploadImage(pasteFile);
|
this.uploadImage(pasteFile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
this.editor.on("mousedown", () => {
|
this.editor.on(`mousedown`, () => {
|
||||||
this.$store.commit("setRightClickMenuVisible", false);
|
this.$store.commit(`setRightClickMenuVisible`, false)
|
||||||
});
|
})
|
||||||
this.editor.on("blur", () => {
|
this.editor.on(`blur`, () => {
|
||||||
//!影响到右键菜单的点击事件,右键菜单的点击事件在组件内通过mousedown触发
|
//!影响到右键菜单的点击事件,右键菜单的点击事件在组件内通过mousedown触发
|
||||||
this.$store.commit("setRightClickMenuVisible", false);
|
this.$store.commit(`setRightClickMenuVisible`, false)
|
||||||
});
|
})
|
||||||
this.editor.on("scroll", () => {
|
this.editor.on(`scroll`, () => {
|
||||||
this.$store.commit("setRightClickMenuVisible", false);
|
this.$store.commit(`setRightClickMenuVisible`, false)
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
initCssEditor() {
|
initCssEditor() {
|
||||||
this.initCssEditorEntity();
|
this.initCssEditorEntity()
|
||||||
// 自动提示
|
// 自动提示
|
||||||
this.cssEditor.on("keyup", (cm, e) => {
|
this.cssEditor.on(`keyup`, (cm, e) => {
|
||||||
if ((e.keyCode >= 65 && e.keyCode <= 90) || e.keyCode === 189) {
|
if ((e.keyCode >= 65 && e.keyCode <= 90) || e.keyCode === 189) {
|
||||||
cm.showHint(e);
|
cm.showHint(e)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
this.cssEditor.on("update", (instance) => {
|
this.cssEditor.on(`update`, (instance) => {
|
||||||
this.cssChanged();
|
this.cssChanged()
|
||||||
saveEditorContent(this.cssEditor, "__css_content");
|
saveEditorContent(this.cssEditor, `__css_content`)
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
cssChanged() {
|
cssChanged() {
|
||||||
let json = css2json(this.cssEditor.getValue(0));
|
let json = css2json(this.cssEditor.getValue(0))
|
||||||
let theme = setFontSize(this.currentSize.replace("px", ""));
|
let theme = setFontSize(this.currentSize.replace(`px`, ``))
|
||||||
|
|
||||||
theme = customCssWithTemplate(json, this.currentColor, theme);
|
theme = customCssWithTemplate(json, this.currentColor, theme)
|
||||||
this.setWxRendererOptions({
|
this.setWxRendererOptions({
|
||||||
theme: theme,
|
theme: theme,
|
||||||
});
|
})
|
||||||
this.onEditorRefresh();
|
this.onEditorRefresh()
|
||||||
},
|
},
|
||||||
// 切换 highlight.js 代码主题
|
// 切换 highlight.js 代码主题
|
||||||
codeThemeChanged() {
|
codeThemeChanged() {
|
||||||
let cssUrl = this.codeTheme;
|
let cssUrl = this.codeTheme
|
||||||
let el = document.getElementById('hljs')
|
let el = document.getElementById(`hljs`)
|
||||||
if (el != undefined) {
|
if (el != undefined) {
|
||||||
el.setAttribute('href', cssUrl);
|
el.setAttribute(`href`, cssUrl)
|
||||||
} else {
|
} else {
|
||||||
var link = document.createElement('link');
|
var link = document.createElement(`link`)
|
||||||
link.setAttribute('type','text/css');
|
link.setAttribute(`type`, `text/css`)
|
||||||
link.setAttribute('rel','stylesheet');
|
link.setAttribute(`rel`, `stylesheet`)
|
||||||
link.setAttribute('href',cssUrl);
|
link.setAttribute(`href`, cssUrl)
|
||||||
link.setAttribute('id','hljs');
|
link.setAttribute(`id`, `hljs`)
|
||||||
document.head.appendChild(link);
|
document.head.appendChild(link)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeUpload(file) {
|
beforeUpload(file) {
|
||||||
// validate image
|
// validate image
|
||||||
const checkResult = checkImage(file);
|
const checkResult = checkImage(file)
|
||||||
if (!checkResult.ok) {
|
if (!checkResult.ok) {
|
||||||
this.$message.error(checkResult.msg);
|
this.$message.error(checkResult.msg)
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// check image host
|
// check image host
|
||||||
let imgHost = localStorage.getItem("imgHost");
|
let imgHost = localStorage.getItem(`imgHost`)
|
||||||
imgHost = imgHost ? imgHost : "default";
|
imgHost = imgHost ? imgHost : `default`
|
||||||
localStorage.setItem("imgHost", imgHost);
|
localStorage.setItem(`imgHost`, imgHost)
|
||||||
|
|
||||||
const config = localStorage.getItem(`${imgHost}Config`);
|
const config = localStorage.getItem(`${imgHost}Config`)
|
||||||
const isValidHost = imgHost == "default" || config;
|
const isValidHost = imgHost == `default` || config
|
||||||
if (!isValidHost) {
|
if (!isValidHost) {
|
||||||
this.$message.error(`请先配置 ${imgHost} 图床参数`);
|
this.$message.error(`请先配置 ${imgHost} 图床参数`)
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
return true;
|
return true
|
||||||
},
|
},
|
||||||
uploadImage(file) {
|
uploadImage(file) {
|
||||||
this.isImgLoading = true;
|
this.isImgLoading = true
|
||||||
toBase64(file)
|
toBase64(file)
|
||||||
.then((base64Content) => {
|
.then((base64Content) => {
|
||||||
fileApi
|
fileApi
|
||||||
.fileUpload(base64Content, file)
|
.fileUpload(base64Content, file)
|
||||||
.then((url) => {
|
.then((url) => {
|
||||||
console.log(url)
|
console.log(url)
|
||||||
this.uploaded(url);
|
this.uploaded(url)
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
this.$message.error(err.message);
|
this.$message.error(err.message)
|
||||||
});
|
})
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
this.$message.error(err.message);
|
this.$message.error(err.message)
|
||||||
});
|
})
|
||||||
this.isImgLoading = false;
|
this.isImgLoading = false
|
||||||
},
|
},
|
||||||
// 图片上传结束
|
// 图片上传结束
|
||||||
uploaded(response) {
|
uploaded(response) {
|
||||||
console.log("图片上传之后: ", response)
|
console.log(`图片上传之后: `, response)
|
||||||
if (!response) {
|
if (!response) {
|
||||||
this.$message.error("上传图片未知异常");
|
this.$message.error(`上传图片未知异常`)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
this.dialogUploadImgVisible = false;
|
this.dialogUploadImgVisible = false
|
||||||
// 上传成功,获取光标
|
// 上传成功,获取光标
|
||||||
const cursor = this.editor.getCursor();
|
const cursor = this.editor.getCursor()
|
||||||
const imageUrl = response;
|
const imageUrl = response
|
||||||
const markdownImage = `![](${imageUrl})`;
|
const markdownImage = `![](${imageUrl})`
|
||||||
// 将 Markdown 形式的 URL 插入编辑框光标所在位置
|
// 将 Markdown 形式的 URL 插入编辑框光标所在位置
|
||||||
this.editor.replaceSelection(`\n${markdownImage}\n`, cursor);
|
this.editor.replaceSelection(`\n${markdownImage}\n`, cursor)
|
||||||
this.$message.success("图片上传成功");
|
this.$message.success(`图片上传成功`)
|
||||||
this.onEditorRefresh();
|
this.onEditorRefresh()
|
||||||
},
|
},
|
||||||
// 左右滚动
|
// 左右滚动
|
||||||
leftAndRightScroll() {
|
leftAndRightScroll() {
|
||||||
const scrollCB = (text) => {
|
const scrollCB = (text) => {
|
||||||
let source, target;
|
let source, target
|
||||||
|
|
||||||
clearTimeout(this.timeout);
|
clearTimeout(this.timeout)
|
||||||
if (text === "preview") {
|
if (text === `preview`) {
|
||||||
source = this.$refs.preview.$el;
|
source = this.$refs.preview.$el
|
||||||
target = document.getElementsByClassName("CodeMirror-scroll")[0];
|
target = document.getElementsByClassName(`CodeMirror-scroll`)[0]
|
||||||
this.editor.off("scroll", editorScrollCB);
|
this.editor.off(`scroll`, editorScrollCB)
|
||||||
this.timeout = setTimeout(() => {
|
this.timeout = setTimeout(() => {
|
||||||
this.editor.on("scroll", editorScrollCB);
|
this.editor.on(`scroll`, editorScrollCB)
|
||||||
}, 300);
|
}, 300)
|
||||||
} else if (text === "editor") {
|
} else if (text === `editor`) {
|
||||||
source = document.getElementsByClassName("CodeMirror-scroll")[0];
|
source = document.getElementsByClassName(`CodeMirror-scroll`)[0]
|
||||||
target = this.$refs.preview.$el;
|
target = this.$refs.preview.$el
|
||||||
target.removeEventListener("scroll", previewScrollCB, false);
|
target.removeEventListener(`scroll`, previewScrollCB, false)
|
||||||
this.timeout = setTimeout(() => {
|
this.timeout = setTimeout(() => {
|
||||||
target.addEventListener("scroll", previewScrollCB, false);
|
target.addEventListener(`scroll`, previewScrollCB, false)
|
||||||
}, 300);
|
}, 300)
|
||||||
}
|
}
|
||||||
|
|
||||||
let percentage =
|
let percentage =
|
||||||
source.scrollTop / (source.scrollHeight - source.offsetHeight);
|
source.scrollTop / (source.scrollHeight - source.offsetHeight)
|
||||||
let height = percentage * (target.scrollHeight - target.offsetHeight);
|
let height = percentage * (target.scrollHeight - target.offsetHeight)
|
||||||
|
|
||||||
target.scrollTo(0, height);
|
target.scrollTo(0, height)
|
||||||
};
|
}
|
||||||
const editorScrollCB = () => {
|
const editorScrollCB = () => {
|
||||||
scrollCB("editor");
|
scrollCB(`editor`)
|
||||||
};
|
}
|
||||||
const previewScrollCB = () => {
|
const previewScrollCB = () => {
|
||||||
scrollCB("preview");
|
scrollCB(`preview`)
|
||||||
};
|
}
|
||||||
|
|
||||||
this.$refs.preview.$el.addEventListener("scroll", previewScrollCB, false);
|
this.$refs.preview.$el.addEventListener(`scroll`, previewScrollCB, false)
|
||||||
this.editor.on("scroll", editorScrollCB);
|
this.editor.on(`scroll`, editorScrollCB)
|
||||||
},
|
},
|
||||||
// 更新编辑器
|
// 更新编辑器
|
||||||
onEditorRefresh() {
|
onEditorRefresh() {
|
||||||
this.codeThemeChanged(this.codeTheme);
|
this.codeThemeChanged(this.codeTheme)
|
||||||
this.editorRefresh();
|
this.editorRefresh()
|
||||||
setTimeout(() => PR.prettyPrint(), 0);
|
setTimeout(() => window.PR.prettyPrint(), 0)
|
||||||
},
|
},
|
||||||
// 复制结束
|
// 复制结束
|
||||||
endCopy() {
|
endCopy() {
|
||||||
this.backLight = false;
|
this.backLight = false
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.isCoping = false;
|
this.isCoping = false
|
||||||
}, 800);
|
}, 800)
|
||||||
},
|
},
|
||||||
// 导出编辑器内容到本地
|
// 导出编辑器内容到本地
|
||||||
downloadEditorContent() {
|
downloadEditorContent() {
|
||||||
downloadMD(this.editor.getValue(0));
|
downloadMD(this.editor.getValue(0))
|
||||||
},
|
},
|
||||||
// 导出编辑器内容为 HTML,并且下载到本地
|
// 导出编辑器内容为 HTML,并且下载到本地
|
||||||
exportEditorContent() {
|
exportEditorContent() {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
exportHTML();
|
exportHTML()
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
// 导入 Markdown 文档
|
// 导入 Markdown 文档
|
||||||
importMarkdownContent() {
|
importMarkdownContent() {
|
||||||
let menu = document.getElementById("menu");
|
let menu = document.getElementById(`menu`)
|
||||||
let input = document.createElement("input");
|
let input = document.createElement(`input`)
|
||||||
input.type = "file";
|
input.type = `file`
|
||||||
input.name = "filename";
|
input.name = `filename`
|
||||||
input.accept = ".txt,.md";
|
input.accept = `.txt,.md`
|
||||||
menu.appendChild(input);
|
menu.appendChild(input)
|
||||||
input.onchange = () => {
|
input.onchange = () => {
|
||||||
if (!input.files) {
|
if (!input.files) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
const file = input.files[0];
|
const file = input.files[0]
|
||||||
if (!/\.(txt|TXT|MD|md)$/.test(file.name)) {
|
if (!/\.(txt|TXT|MD|md)$/.test(file.name)) {
|
||||||
this.$message.error("不支持的文档格式");
|
this.$message.error(`不支持的文档格式`)
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
const reader = new FileReader();
|
const reader = new FileReader()
|
||||||
reader.readAsText(file);
|
reader.readAsText(file)
|
||||||
reader.onload = (event) => {
|
reader.onload = (event) => {
|
||||||
let txt = event.target.result;
|
let txt = event.target.result
|
||||||
txt = formatDoc(txt);
|
txt = formatDoc(txt)
|
||||||
if (txt) {
|
if (txt) {
|
||||||
localStorage.setItem("__editor_content", txt);
|
localStorage.setItem(`__editor_content`, txt)
|
||||||
this.editor.setValue(txt);
|
this.editor.setValue(txt)
|
||||||
this.$message.success("文档导入成功");
|
this.$message.success(`文档导入成功`)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
input.click();
|
input.click()
|
||||||
menu.removeChild(input);
|
menu.removeChild(input)
|
||||||
},
|
},
|
||||||
// 格式化文档
|
// 格式化文档
|
||||||
formatContent() {
|
formatContent() {
|
||||||
const doc = formatDoc(this.editor.getValue(0));
|
const doc = formatDoc(this.editor.getValue(0))
|
||||||
localStorage.setItem("__editor_content", doc);
|
localStorage.setItem(`__editor_content`, doc)
|
||||||
this.editor.setValue(doc);
|
this.editor.setValue(doc)
|
||||||
},
|
},
|
||||||
// 右键菜单
|
// 右键菜单
|
||||||
openMenu(e) {
|
openMenu(e) {
|
||||||
const menuMinWidth = 105;
|
const menuMinWidth = 105
|
||||||
const offsetLeft = this.$el.getBoundingClientRect().left;
|
const offsetLeft = this.$el.getBoundingClientRect().left
|
||||||
const offsetWidth = this.$el.offsetWidth;
|
const offsetWidth = this.$el.offsetWidth
|
||||||
const maxLeft = offsetWidth - menuMinWidth;
|
const maxLeft = offsetWidth - menuMinWidth
|
||||||
const left = e.clientX - offsetLeft;
|
const left = e.clientX - offsetLeft
|
||||||
this.mouseLeft = Math.min(maxLeft, left);
|
this.mouseLeft = Math.min(maxLeft, left)
|
||||||
this.mouseTop = e.clientY + 10;
|
this.mouseTop = e.clientY + 10
|
||||||
this.$store.commit("setRightClickMenuVisible", true);
|
this.$store.commit(`setRightClickMenuVisible`, true)
|
||||||
},
|
},
|
||||||
closeRightClickMenu() {
|
closeRightClickMenu() {
|
||||||
this.$store.commit("setRightClickMenuVisible", false);
|
this.$store.commit(`setRightClickMenuVisible`, false)
|
||||||
},
|
},
|
||||||
onMenuEvent(type, info = {}) {
|
onMenuEvent(type, info = {}) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "resetStyle":
|
case `resetStyle`:
|
||||||
this.$refs.header.showResetConfirm = true;
|
this.$refs.header.showResetConfirm = true
|
||||||
break;
|
break
|
||||||
case "insertPic":
|
case `insertPic`:
|
||||||
this.dialogUploadImgVisible = true;
|
this.dialogUploadImgVisible = true
|
||||||
break;
|
break
|
||||||
case "download":
|
case `download`:
|
||||||
this.downloadEditorContent();
|
this.downloadEditorContent()
|
||||||
break;
|
break
|
||||||
case "export":
|
case `export`:
|
||||||
this.exportEditorContent();
|
this.exportEditorContent()
|
||||||
break;
|
break
|
||||||
case "insertTable":
|
case `insertTable`:
|
||||||
this.dialogFormVisible = true;
|
this.dialogFormVisible = true
|
||||||
break;
|
break
|
||||||
case "importMarkdown":
|
case `importMarkdown`:
|
||||||
this.importMarkdownContent();
|
this.importMarkdownContent()
|
||||||
break;
|
break
|
||||||
case "formatMarkdown":
|
case `formatMarkdown`:
|
||||||
this.formatContent();
|
this.formatContent()
|
||||||
break;
|
break
|
||||||
default:
|
default:
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
...mapMutations([
|
...mapMutations([
|
||||||
"initEditorState",
|
`initEditorState`,
|
||||||
"initEditorEntity",
|
`initEditorEntity`,
|
||||||
"setWxRendererOptions",
|
`setWxRendererOptions`,
|
||||||
"editorRefresh",
|
`editorRefresh`,
|
||||||
"initCssEditorEntity",
|
`initCssEditorEntity`,
|
||||||
]),
|
]),
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.leftAndRightScroll();
|
this.leftAndRightScroll()
|
||||||
PR.prettyPrint();
|
window.PR.prettyPrint()
|
||||||
}, 300);
|
}, 300)
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@ -506,7 +506,7 @@ export default {
|
|||||||
width: 50px;
|
width: 50px;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
background: url("../../../assets/images/favicon.png") no-repeat;
|
background: url('../../../assets/images/favicon.png') no-repeat;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
}
|
}
|
||||||
span {
|
span {
|
||||||
@ -556,5 +556,5 @@ export default {
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
@import url("../../../assets/less/app.less");
|
@import url('../../../assets/less/app.less');
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
import Vue from "vue";
|
import Vue from 'vue'
|
||||||
import {
|
import { Loading, Message } from 'element-ui'
|
||||||
Loading,
|
|
||||||
Message,
|
|
||||||
} from "element-ui";
|
|
||||||
|
|
||||||
Vue.component(Message.name, Message);
|
Vue.component(Message.name, Message)
|
||||||
|
|
||||||
Vue.prototype.$loading = Loading.service;
|
Vue.prototype.$loading = Loading.service
|
||||||
Vue.prototype.$message = Message;
|
Vue.prototype.$message = Message
|
||||||
|
@ -9,7 +9,7 @@ const routes = [
|
|||||||
path: `/`,
|
path: `/`,
|
||||||
name: `index`,
|
name: `index`,
|
||||||
component: index,
|
component: index,
|
||||||
}
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
const router = new VueRouter({
|
const router = new VueRouter({
|
||||||
|
@ -1,162 +1,162 @@
|
|||||||
import Vue from "vue";
|
import Vue from 'vue'
|
||||||
import Vuex from "vuex";
|
import Vuex from 'vuex'
|
||||||
import config from "../assets/scripts/config";
|
import config from '../assets/scripts/config'
|
||||||
import WxRenderer from "../assets/scripts/renderers/wx-renderer";
|
import WxRenderer from '../assets/scripts/renderers/wx-renderer'
|
||||||
import { marked } from "marked";
|
import { marked } from 'marked'
|
||||||
import CodeMirror from "codemirror/lib/codemirror";
|
import CodeMirror from 'codemirror/lib/codemirror'
|
||||||
import DEFAULT_CONTENT from "@/assets/example/markdown.md";
|
import DEFAULT_CONTENT from '@/assets/example/markdown.md'
|
||||||
import DEFAULT_CSS_CONTENT from "@/assets/example/theme-css.txt";
|
import DEFAULT_CSS_CONTENT from '@/assets/example/theme-css.txt'
|
||||||
import { setColor, formatDoc, formatCss } from "../assets/scripts/util";
|
import { setColor, formatDoc, formatCss } from '../assets/scripts/util'
|
||||||
|
|
||||||
Vue.use(Vuex);
|
Vue.use(Vuex)
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
wxRenderer: null,
|
wxRenderer: null,
|
||||||
output: "",
|
output: ``,
|
||||||
html: "",
|
html: ``,
|
||||||
editor: null,
|
editor: null,
|
||||||
cssEditor: null,
|
cssEditor: null,
|
||||||
currentFont: "",
|
currentFont: ``,
|
||||||
currentSize: "",
|
currentSize: ``,
|
||||||
currentColor: "",
|
currentColor: ``,
|
||||||
citeStatus: 0,
|
citeStatus: 0,
|
||||||
nightMode: false,
|
nightMode: false,
|
||||||
codeTheme: config.codeThemeOption[0].value,
|
codeTheme: config.codeThemeOption[0].value,
|
||||||
rightClickMenuVisible: false,
|
rightClickMenuVisible: false,
|
||||||
};
|
}
|
||||||
const mutations = {
|
const mutations = {
|
||||||
setEditorValue(state, data) {
|
setEditorValue(state, data) {
|
||||||
state.editor.setValue(data);
|
state.editor.setValue(data)
|
||||||
},
|
},
|
||||||
setCssEditorValue(state, data) {
|
setCssEditorValue(state, data) {
|
||||||
state.cssEditor.setValue(data);
|
state.cssEditor.setValue(data)
|
||||||
},
|
},
|
||||||
setWxRendererOptions(state, data) {
|
setWxRendererOptions(state, data) {
|
||||||
state.wxRenderer.setOptions(data);
|
state.wxRenderer.setOptions(data)
|
||||||
},
|
},
|
||||||
setCiteStatus(state, data) {
|
setCiteStatus(state, data) {
|
||||||
state.citeStatus = data;
|
state.citeStatus = data
|
||||||
localStorage.setItem("citeStatus", data);
|
localStorage.setItem(`citeStatus`, data)
|
||||||
},
|
},
|
||||||
setCurrentFont(state, data) {
|
setCurrentFont(state, data) {
|
||||||
state.currentFont = data;
|
state.currentFont = data
|
||||||
localStorage.setItem("fonts", data);
|
localStorage.setItem(`fonts`, data)
|
||||||
},
|
},
|
||||||
setCurrentSize(state, data) {
|
setCurrentSize(state, data) {
|
||||||
state.currentSize = data;
|
state.currentSize = data
|
||||||
localStorage.setItem("size", data);
|
localStorage.setItem(`size`, data)
|
||||||
},
|
},
|
||||||
setCurrentColor(state, data) {
|
setCurrentColor(state, data) {
|
||||||
state.currentColor = data;
|
state.currentColor = data
|
||||||
localStorage.setItem("color", data);
|
localStorage.setItem(`color`, data)
|
||||||
},
|
},
|
||||||
setCurrentCodeTheme(state, data) {
|
setCurrentCodeTheme(state, data) {
|
||||||
state.codeTheme = data;
|
state.codeTheme = data
|
||||||
localStorage.setItem("codeTheme", data);
|
localStorage.setItem(`codeTheme`, data)
|
||||||
},
|
},
|
||||||
setRightClickMenuVisible(state, data) {
|
setRightClickMenuVisible(state, data) {
|
||||||
state.rightClickMenuVisible = data;
|
state.rightClickMenuVisible = data
|
||||||
},
|
},
|
||||||
themeChanged(state) {
|
themeChanged(state) {
|
||||||
state.nightMode = !state.nightMode;
|
state.nightMode = !state.nightMode
|
||||||
localStorage.setItem("nightMode", state.nightMode);
|
localStorage.setItem(`nightMode`, state.nightMode)
|
||||||
},
|
},
|
||||||
initEditorState(state) {
|
initEditorState(state) {
|
||||||
state.currentFont =
|
state.currentFont =
|
||||||
localStorage.getItem("fonts") || config.builtinFonts[0].value;
|
localStorage.getItem(`fonts`) || config.builtinFonts[0].value
|
||||||
state.currentColor =
|
state.currentColor =
|
||||||
localStorage.getItem("color") || config.colorOption[0].value;
|
localStorage.getItem(`color`) || config.colorOption[0].value
|
||||||
state.currentSize =
|
state.currentSize =
|
||||||
localStorage.getItem("size") || config.sizeOption[2].value;
|
localStorage.getItem(`size`) || config.sizeOption[2].value
|
||||||
state.codeTheme =
|
state.codeTheme =
|
||||||
localStorage.getItem("codeTheme") || config.codeThemeOption[0].value;
|
localStorage.getItem(`codeTheme`) || config.codeThemeOption[0].value
|
||||||
state.citeStatus = localStorage.getItem("citeStatus") === "true";
|
state.citeStatus = localStorage.getItem(`citeStatus`) === `true`
|
||||||
state.nightMode = localStorage.getItem("nightMode") === "true";
|
state.nightMode = localStorage.getItem(`nightMode`) === `true`
|
||||||
state.wxRenderer = new WxRenderer({
|
state.wxRenderer = new WxRenderer({
|
||||||
theme: setColor(state.currentColor),
|
theme: setColor(state.currentColor),
|
||||||
fonts: state.currentFont,
|
fonts: state.currentFont,
|
||||||
size: state.currentSize,
|
size: state.currentSize,
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
initEditorEntity(state) {
|
initEditorEntity(state) {
|
||||||
const editorDom = document.getElementById("editor");
|
const editorDom = document.getElementById(`editor`)
|
||||||
|
|
||||||
if (!editorDom.value) {
|
if (!editorDom.value) {
|
||||||
editorDom.value =
|
editorDom.value =
|
||||||
localStorage.getItem("__editor_content") || formatDoc(DEFAULT_CONTENT);
|
localStorage.getItem(`__editor_content`) || formatDoc(DEFAULT_CONTENT)
|
||||||
}
|
}
|
||||||
state.editor = CodeMirror.fromTextArea(editorDom, {
|
state.editor = CodeMirror.fromTextArea(editorDom, {
|
||||||
mode: "text/x-markdown",
|
mode: `text/x-markdown`,
|
||||||
theme: "xq-light",
|
theme: `xq-light`,
|
||||||
lineNumbers: false,
|
lineNumbers: false,
|
||||||
lineWrapping: true,
|
lineWrapping: true,
|
||||||
styleActiveLine: true,
|
styleActiveLine: true,
|
||||||
autoCloseBrackets: true,
|
autoCloseBrackets: true,
|
||||||
extraKeys: {
|
extraKeys: {
|
||||||
"Ctrl-F": function autoFormat(editor) {
|
'Ctrl-F': function autoFormat(editor) {
|
||||||
const doc = formatDoc(editor.getValue(0));
|
const doc = formatDoc(editor.getValue(0))
|
||||||
localStorage.setItem("__editor_content", doc);
|
localStorage.setItem(`__editor_content`, doc)
|
||||||
editor.setValue(doc);
|
editor.setValue(doc)
|
||||||
},
|
},
|
||||||
"Ctrl-S": function save(editor) {},
|
'Ctrl-S': function save(editor) {},
|
||||||
"Ctrl-B": function bold(editor) {
|
'Ctrl-B': function bold(editor) {
|
||||||
const selected = editor.getSelection();
|
const selected = editor.getSelection()
|
||||||
editor.replaceSelection(`**${selected}**`);
|
editor.replaceSelection(`**${selected}**`)
|
||||||
},
|
},
|
||||||
"Ctrl-D": function del(editor) {
|
'Ctrl-D': function del(editor) {
|
||||||
const selected = editor.getSelection();
|
const selected = editor.getSelection()
|
||||||
editor.replaceSelection(`~~${selected}~~`);
|
editor.replaceSelection(`~~${selected}~~`)
|
||||||
},
|
},
|
||||||
"Ctrl-I": function italic(editor) {
|
'Ctrl-I': function italic(editor) {
|
||||||
const selected = editor.getSelection();
|
const selected = editor.getSelection()
|
||||||
editor.replaceSelection(`*${selected}*`);
|
editor.replaceSelection(`*${selected}*`)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
initCssEditorEntity(state) {
|
initCssEditorEntity(state) {
|
||||||
const cssEditorDom = document.getElementById("cssEditor");
|
const cssEditorDom = document.getElementById(`cssEditor`)
|
||||||
|
|
||||||
if (!cssEditorDom.value) {
|
if (!cssEditorDom.value) {
|
||||||
cssEditorDom.value =
|
cssEditorDom.value =
|
||||||
localStorage.getItem("__css_content") || DEFAULT_CSS_CONTENT;
|
localStorage.getItem(`__css_content`) || DEFAULT_CSS_CONTENT
|
||||||
}
|
}
|
||||||
state.cssEditor = CodeMirror.fromTextArea(cssEditorDom, {
|
state.cssEditor = CodeMirror.fromTextArea(cssEditorDom, {
|
||||||
mode: "css",
|
mode: `css`,
|
||||||
theme: "style-mirror",
|
theme: `style-mirror`,
|
||||||
lineNumbers: false,
|
lineNumbers: false,
|
||||||
lineWrapping: true,
|
lineWrapping: true,
|
||||||
matchBrackets: true,
|
matchBrackets: true,
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
extraKeys: {
|
extraKeys: {
|
||||||
"Ctrl-F": function autoFormat(editor) {
|
'Ctrl-F': function autoFormat(editor) {
|
||||||
const doc = formatCss(editor.getValue(0));
|
const doc = formatCss(editor.getValue(0))
|
||||||
localStorage.setItem("__css_content", doc);
|
localStorage.setItem(`__css_content`, doc)
|
||||||
editor.setValue(doc);
|
editor.setValue(doc)
|
||||||
},
|
},
|
||||||
"Ctrl-S": function save(editor) {},
|
'Ctrl-S': function save(editor) {},
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
editorRefresh(state) {
|
editorRefresh(state) {
|
||||||
let renderer = state.wxRenderer.getRenderer(state.citeStatus);
|
let renderer = state.wxRenderer.getRenderer(state.citeStatus)
|
||||||
marked.setOptions({ renderer });
|
marked.setOptions({ renderer })
|
||||||
let output = marked.parse(state.editor.getValue(0));
|
let output = marked.parse(state.editor.getValue(0))
|
||||||
|
|
||||||
// 去除第一行的 margin-top
|
// 去除第一行的 margin-top
|
||||||
output = output.replace(/(style=".*?)"/, '$1;margin-top: 0"');
|
output = output.replace(/(style=".*?)"/, `$1;margin-top: 0"`)
|
||||||
if (state.citeStatus) {
|
if (state.citeStatus) {
|
||||||
// 引用脚注
|
// 引用脚注
|
||||||
output += state.wxRenderer.buildFootnotes();
|
output += state.wxRenderer.buildFootnotes()
|
||||||
// 附加的一些 style
|
// 附加的一些 style
|
||||||
output += state.wxRenderer.buildAddition();
|
output += state.wxRenderer.buildAddition()
|
||||||
}
|
}
|
||||||
state.output = output;
|
state.output = output
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|
||||||
export default new Vuex.Store({
|
export default new Vuex.Store({
|
||||||
state,
|
state,
|
||||||
mutations,
|
mutations,
|
||||||
actions: {},
|
actions: {},
|
||||||
});
|
})
|
||||||
|
@ -5,9 +5,11 @@ module.exports = {
|
|||||||
configureWebpack: (config) => {
|
configureWebpack: (config) => {
|
||||||
config.module.rules.push({
|
config.module.rules.push({
|
||||||
test: /\.(txt|md)$/i,
|
test: /\.(txt|md)$/i,
|
||||||
use: [{
|
use: [
|
||||||
loader: 'raw-loader',
|
{
|
||||||
}]
|
loader: `raw-loader`,
|
||||||
|
},
|
||||||
|
],
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
productionSourceMap: !isProd,
|
productionSourceMap: !isProd,
|
||||||
|
Loading…
Reference in New Issue
Block a user