mirror of
https://github.com/doocs/md.git
synced 2024-11-24 19:10:34 +08:00
docs: prettify code
This commit is contained in:
parent
3493829419
commit
90d9b86fe6
33
.eslintrc.js
33
.eslintrc.js
@ -1,28 +1,27 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
root: true,
|
root: true,
|
||||||
env: {
|
env: {
|
||||||
node: true
|
node: true,
|
||||||
},
|
},
|
||||||
'extends': [
|
extends: ["plugin:vue/essential", "@vue/standard"],
|
||||||
'plugin:vue/essential',
|
|
||||||
'@vue/standard'
|
|
||||||
],
|
|
||||||
rules: {
|
rules: {
|
||||||
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
"no-console": process.env.NODE_ENV === "production" ? "error" : "off",
|
||||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "off",
|
||||||
'camelcase': 'off',
|
camelcase: "off",
|
||||||
'eqeqeq': 'off'
|
eqeqeq: "off",
|
||||||
},
|
},
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
parser: 'babel-eslint'
|
parser: "babel-eslint",
|
||||||
},
|
},
|
||||||
overrides: [{
|
overrides: [
|
||||||
|
{
|
||||||
files: [
|
files: [
|
||||||
'**/__tests__/*.{j,t}s?(x)',
|
"**/__tests__/*.{j,t}s?(x)",
|
||||||
'**/tests/unit/**/*.spec.{j,t}s?(x)'
|
"**/tests/unit/**/*.spec.{j,t}s?(x)",
|
||||||
],
|
],
|
||||||
env: {
|
env: {
|
||||||
jest: true
|
jest: true,
|
||||||
}
|
},
|
||||||
}]
|
},
|
||||||
}
|
],
|
||||||
|
};
|
||||||
|
17
README.md
17
README.md
@ -1,10 +1,9 @@
|
|||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
[![doocs-md](./public/assets/images/logo-2.png)](https://github.com/doocs/md)
|
[![doocs-md](./public/assets/images/logo-2.png)](https://github.com/doocs/md)
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<h1 align="center">微信 Markdown 编辑器</h1>
|
<h1 align="center">微信 Markdown 编辑器</h1>
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
@ -13,14 +12,12 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
## 项目介绍
|
## 项目介绍
|
||||||
|
|
||||||
> 本项目基于 [wechat-format](https://github.com/lyricat/wechat-format) 进行二次开发,感谢 [lyricat](https://github.com/lyricat) 的创意和贡献!
|
> 本项目基于 [wechat-format](https://github.com/lyricat/wechat-format) 进行二次开发,感谢 [lyricat](https://github.com/lyricat) 的创意和贡献!
|
||||||
|
|
||||||
Markdown 文档自动即时渲染为微信图文,让你不再为微信文章排版而发愁!只要你会基本的 Markdown 语法,就能做出一篇样式简洁而又美观大方的微信图文。
|
Markdown 文档自动即时渲染为微信图文,让你不再为微信文章排版而发愁!只要你会基本的 Markdown 语法,就能做出一篇样式简洁而又美观大方的微信图文。
|
||||||
|
|
||||||
|
|
||||||
## 在线编辑器地址
|
## 在线编辑器地址
|
||||||
|
|
||||||
- Gitee Pages:https://doocs.gitee.io/md
|
- Gitee Pages:https://doocs.gitee.io/md
|
||||||
@ -28,7 +25,6 @@ Markdown 文档自动即时渲染为微信图文,让你不再为微信文章
|
|||||||
|
|
||||||
注:推荐使用 Chrome 浏览器,效果最佳。另外,对于国内(中国)的朋友,访问 [Gitee Pages](https://doocs.gitee.io/md) 速度会相对快一些。
|
注:推荐使用 Chrome 浏览器,效果最佳。另外,对于国内(中国)的朋友,访问 [Gitee Pages](https://doocs.gitee.io/md) 速度会相对快一些。
|
||||||
|
|
||||||
|
|
||||||
## 为何二次开发
|
## 为何二次开发
|
||||||
|
|
||||||
现有的开源微信 Markdown 编辑器,样式繁杂,也不符合我个人的审美需求。在我使用它们进行文章排版的时候,经常还要自己做一些改动,费时费力,因此动手做了二次开发。
|
现有的开源微信 Markdown 编辑器,样式繁杂,也不符合我个人的审美需求。在我使用它们进行文章排版的时候,经常还要自己做一些改动,费时费力,因此动手做了二次开发。
|
||||||
@ -48,13 +44,12 @@ Markdown 文档自动即时渲染为微信图文,让你不再为微信文章
|
|||||||
## 目前支持哪些图床
|
## 目前支持哪些图床
|
||||||
|
|
||||||
| # | 图床 | 使用时是否需要配置 | 备注 |
|
| # | 图床 | 使用时是否需要配置 | 备注 |
|
||||||
|---|---|---|---|
|
| --- | ----------- | ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
|
||||||
| 1 | 默认图床 | 否 | - |
|
| 1 | 默认图床 | 否 | - |
|
||||||
| 2 | GitHub 图床 | 配置 `Repo`、`Token` 参数 | [如何获取 GitHub token?](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) |
|
| 2 | GitHub 图床 | 配置 `Repo`、`Token` 参数 | [如何获取 GitHub token?](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) |
|
||||||
| 3 | 阿里云 OSS | 配置 `AccessKey ID`、`AccessKey Secret`、`Bucket`、`Region` 等参数 | [如何使用阿里云 OSS?](https://help.aliyun.com/document_detail/31883.html) |
|
| 3 | 阿里云 OSS | 配置 `AccessKey ID`、`AccessKey Secret`、`Bucket`、`Region` 等参数 | [如何使用阿里云 OSS?](https://help.aliyun.com/document_detail/31883.html) |
|
||||||
| 4 | 腾讯云 COS | 配置 `SecretId`、`SecretKey`、`Bucket`、`Region` 等参数 | [如何使用腾讯云 COS?](https://cloud.tencent.com/document/product/436/38484) |
|
| 4 | 腾讯云 COS | 配置 `SecretId`、`SecretKey`、`Bucket`、`Region` 等参数 | [如何使用腾讯云 COS?](https://cloud.tencent.com/document/product/436/38484) |
|
||||||
|
|
||||||
|
|
||||||
![select-and-change-color-theme](./public/assets/images/select-and-change-color-theme.gif)
|
![select-and-change-color-theme](./public/assets/images/select-and-change-color-theme.gif)
|
||||||
|
|
||||||
![copy-and-paste](./public/assets/images/copy-and-paste.gif)
|
![copy-and-paste](./public/assets/images/copy-and-paste.gif)
|
||||||
@ -63,7 +58,6 @@ Markdown 文档自动即时渲染为微信图文,让你不再为微信文章
|
|||||||
|
|
||||||
![doocs-md-upload-image](./public/assets/images/doocs-md-upload-image.gif)
|
![doocs-md-upload-image](./public/assets/images/doocs-md-upload-image.gif)
|
||||||
|
|
||||||
|
|
||||||
## 谁在使用
|
## 谁在使用
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
@ -165,20 +159,18 @@ Markdown 文档自动即时渲染为微信图文,让你不再为微信文章
|
|||||||
|
|
||||||
注:如果你使用了本 Markdown 编辑器进行文章排版,并且希望在本项目 README 中展示你的公众号,请到 [#5](https://github.com/doocs/md/issues/5) 留言。
|
注:如果你使用了本 Markdown 编辑器进行文章排版,并且希望在本项目 README 中展示你的公众号,请到 [#5](https://github.com/doocs/md/issues/5) 留言。
|
||||||
|
|
||||||
|
|
||||||
## 项目许可证
|
## 项目许可证
|
||||||
|
|
||||||
[本项目没有任何限制,Just Do What The F*ck You Want。](LICENSE)
|
[本项目没有任何限制,Just Do What The F\*ck You Want。](LICENSE)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
## Doocs 社区优质项目
|
## Doocs 社区优质项目
|
||||||
|
|
||||||
Doocs 技术社区,致力于打造一个内容完整、持续成长的互联网开发者学习生态圈!以下是 Doocs 旗下的一些优秀项目,欢迎各位开发者朋友持续保持关注。
|
Doocs 技术社区,致力于打造一个内容完整、持续成长的互联网开发者学习生态圈!以下是 Doocs 旗下的一些优秀项目,欢迎各位开发者朋友持续保持关注。
|
||||||
|
|
||||||
| # | 项目 | 描述 | 热度 |
|
| # | 项目 | 描述 | 热度 |
|
||||||
|---|---|---|---|
|
| --- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| 1 | [advanced-java](https://github.com/doocs/advanced-java) | 互联网 Java 工程师进阶知识完全扫盲:涵盖高并发、分布式、高可用、微服务、海量数据处理等领域知识。 | ![](https://badgen.net/github/stars/doocs/advanced-java) <br>![](https://badgen.net/github/forks/doocs/advanced-java) |
|
| 1 | [advanced-java](https://github.com/doocs/advanced-java) | 互联网 Java 工程师进阶知识完全扫盲:涵盖高并发、分布式、高可用、微服务、海量数据处理等领域知识。 | ![](https://badgen.net/github/stars/doocs/advanced-java) <br>![](https://badgen.net/github/forks/doocs/advanced-java) |
|
||||||
| 2 | [leetcode](https://github.com/doocs/leetcode) | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解。 | ![](https://badgen.net/github/stars/doocs/leetcode) <br>![](https://badgen.net/github/forks/doocs/leetcode) |
|
| 2 | [leetcode](https://github.com/doocs/leetcode) | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解。 | ![](https://badgen.net/github/stars/doocs/leetcode) <br>![](https://badgen.net/github/forks/doocs/leetcode) |
|
||||||
| 3 | [source-code-hunter](https://github.com/doocs/source-code-hunter) | 互联网常用组件框架源码分析。 | ![](https://badgen.net/github/stars/doocs/source-code-hunter) <br>![](https://badgen.net/github/forks/doocs/source-code-hunter) |
|
| 3 | [source-code-hunter](https://github.com/doocs/source-code-hunter) | 互联网常用组件框架源码分析。 | ![](https://badgen.net/github/stars/doocs/source-code-hunter) <br>![](https://badgen.net/github/forks/doocs/source-code-hunter) |
|
||||||
@ -187,7 +179,6 @@ Doocs 技术社区,致力于打造一个内容完整、持续成长的互联
|
|||||||
| 6 | [md](https://github.com/doocs/md) | 一款高度简洁的微信 Markdown 编辑器。 | ![](https://badgen.net/github/stars/doocs/md) <br>![](https://badgen.net/github/forks/doocs/md) |
|
| 6 | [md](https://github.com/doocs/md) | 一款高度简洁的微信 Markdown 编辑器。 | ![](https://badgen.net/github/stars/doocs/md) <br>![](https://badgen.net/github/forks/doocs/md) |
|
||||||
| 7 | [technical-books](https://github.com/doocs/technical-books) | 值得一看的技术书籍列表。 | ![](https://badgen.net/github/stars/doocs/technical-books) <br>![](https://badgen.net/github/forks/doocs/technical-books) |
|
| 7 | [technical-books](https://github.com/doocs/technical-books) | 值得一看的技术书籍列表。 | ![](https://badgen.net/github/stars/doocs/technical-books) <br>![](https://badgen.net/github/forks/doocs/technical-books) |
|
||||||
|
|
||||||
|
|
||||||
## 贡献者
|
## 贡献者
|
||||||
|
|
||||||
感谢以下所有朋友对 [Doocs 技术社区](https://github.com/doocs) 所做出的贡献,[参与项目维护请戳这儿](https://doocs.github.io/#/?id=how-to-join)。
|
感谢以下所有朋友对 [Doocs 技术社区](https://github.com/doocs) 所做出的贡献,[参与项目维护请戳这儿](https://doocs.github.io/#/?id=how-to-join)。
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
presets: [
|
presets: ["@vue/cli-plugin-babel/preset"],
|
||||||
'@vue/cli-plugin-babel/preset'
|
};
|
||||||
]
|
|
||||||
}
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
preset: '@vue/cli-plugin-unit-jest'
|
preset: "@vue/cli-plugin-unit-jest",
|
||||||
}
|
};
|
||||||
|
@ -1,23 +1,33 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
<head>
|
||||||
<head>
|
<meta charset="UTF-8" />
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||||
<meta name="keywords" content="md,markdown,markdown-editor,wechat,official-account,yanglbme,doocs">
|
<meta
|
||||||
<meta name="description" content="Wechat Markdown Editor | 一款高度简洁的微信 Markdown 编辑器">
|
name="keywords"
|
||||||
<meta name="viewport"
|
content="md,markdown,markdown-editor,wechat,official-account,yanglbme,doocs"
|
||||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
/>
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content="Wechat Markdown Editor | 一款高度简洁的微信 Markdown 编辑器"
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
|
||||||
|
/>
|
||||||
<title>微信 Markdown 编辑器</title>
|
<title>微信 Markdown 编辑器</title>
|
||||||
<link rel="shortcut icon" href="https://gitee.com/yanglbme/resource/raw/master/doocs-md/favicon.png">
|
<link
|
||||||
<link rel="apple-touch-icon-precomposed"
|
rel="shortcut icon"
|
||||||
href="https://gitee.com/yanglbme/resource/raw/master/doocs-md/qrcode.png">
|
href="https://gitee.com/yanglbme/resource/raw/master/doocs-md/favicon.png"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
rel="apple-touch-icon-precomposed"
|
||||||
|
href="https://gitee.com/yanglbme/resource/raw/master/doocs-md/qrcode.png"
|
||||||
|
/>
|
||||||
<script src="https://cdn.bootcdn.net/ajax/libs/prettify/r224/prettify.min.js"></script>
|
<script src="https://cdn.bootcdn.net/ajax/libs/prettify/r224/prettify.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="app">
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
@ -1,26 +1,30 @@
|
|||||||
import axios from 'axios';
|
import axios from "axios";
|
||||||
|
|
||||||
// 创建axios实例
|
// 创建axios实例
|
||||||
const service = axios.create({
|
const service = axios.create({
|
||||||
baseURL: '',
|
baseURL: "",
|
||||||
timeout: 10 * 1000 // 请求超时时间
|
timeout: 10 * 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(res => {
|
service.interceptors.response.use(
|
||||||
|
(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;
|
156
src/api/file.js
156
src/api/file.js
@ -1,37 +1,35 @@
|
|||||||
import fetch from './fetch';
|
import fetch from "./fetch";
|
||||||
import OSS from 'ali-oss';
|
import OSS from "ali-oss";
|
||||||
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 {
|
import { v4 as uuidv4 } from "uuid";
|
||||||
v4 as uuidv4
|
import { resolveConfigFile } from "prettier";
|
||||||
} from 'uuid';
|
|
||||||
import { resolveConfigFile } from 'prettier';
|
|
||||||
|
|
||||||
const defaultConfig = {
|
const defaultConfig = {
|
||||||
username: 'filess',
|
username: "filess",
|
||||||
repo: 'images',
|
repo: "images",
|
||||||
branch: 'master',
|
branch: "master",
|
||||||
accessToken: [
|
accessToken: [
|
||||||
'7715d7ca67b5d3837cfdoocsmde8c38421815aa423510af',
|
"7715d7ca67b5d3837cfdoocsmde8c38421815aa423510af",
|
||||||
'c411415bf95dbe39625doocsmd5047ba9b7a2a6c9642abe',
|
"c411415bf95dbe39625doocsmd5047ba9b7a2a6c9642abe",
|
||||||
'2821cd8819fa345c053doocsmdca86ac653f8bc20db1f1b',
|
"2821cd8819fa345c053doocsmdca86ac653f8bc20db1f1b",
|
||||||
'445f0dae46ef1f2a4d6doocsmdc797301e94797b4750a4c',
|
"445f0dae46ef1f2a4d6doocsmdc797301e94797b4750a4c",
|
||||||
'cc1d0c1426d0fd0902bdoocsmdd2d7184b14da61b86ec46',
|
"cc1d0c1426d0fd0902bdoocsmdd2d7184b14da61b86ec46",
|
||||||
'b67e9d15cb6f910492fdoocsmdac6b44d379c953bb19eff',
|
"b67e9d15cb6f910492fdoocsmdac6b44d379c953bb19eff",
|
||||||
'618c4dc2244ccbbc088doocsmd125d17fd31b7d06a50cf3',
|
"618c4dc2244ccbbc088doocsmd125d17fd31b7d06a50cf3",
|
||||||
'a4b581732e1c1507458doocsmdc5b223b27dae5e2e16a55'
|
"a4b581732e1c1507458doocsmdc5b223b27dae5e2e16a55",
|
||||||
]
|
],
|
||||||
}
|
};
|
||||||
|
|
||||||
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 'txCOS':
|
case "txCOS":
|
||||||
return txCOSFileUpload(file);
|
return txCOSFileUpload(file);
|
||||||
case 'github':
|
case "github":
|
||||||
default:
|
default:
|
||||||
return ghFileUpload(content, file.name);
|
return ghFileUpload(content, file.name);
|
||||||
}
|
}
|
||||||
@ -39,96 +37,136 @@ function fileUpload(content, file) {
|
|||||||
|
|
||||||
function getGitHubCommonConfig(username, repo, branch, token) {
|
function getGitHubCommonConfig(username, repo, branch, token) {
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
const dir = date.getFullYear() + '/' + (date.getMonth() + 1).toString().padStart(2, '0') + '/' + date.getDate().toString().padStart(2, '0');
|
const dir =
|
||||||
|
date.getFullYear() +
|
||||||
|
"/" +
|
||||||
|
(date.getMonth() + 1).toString().padStart(2, "0") +
|
||||||
|
"/" +
|
||||||
|
date.getDate().toString().padStart(2, "0");
|
||||||
return {
|
return {
|
||||||
method: 'put',
|
method: "put",
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'token ' + token
|
Authorization: "token " + token,
|
||||||
},
|
},
|
||||||
branch: branch,
|
branch: branch,
|
||||||
url: `https://api.github.com/repos/${username}/${repo}/contents/${dir}/`
|
url: `https://api.github.com/repos/${username}/${repo}/contents/${dir}/`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDefaultConfig() {
|
function getDefaultConfig() {
|
||||||
const token = defaultConfig.accessToken[Math.floor(Math.random() * defaultConfig.accessToken.length)].replace('doocsmd', '');
|
const token = defaultConfig.accessToken[
|
||||||
return getGitHubCommonConfig(defaultConfig.username, defaultConfig.repo, defaultConfig.branch, token);
|
Math.floor(Math.random() * defaultConfig.accessToken.length)
|
||||||
|
].replace("doocsmd", "");
|
||||||
|
return getGitHubCommonConfig(
|
||||||
|
defaultConfig.username,
|
||||||
|
defaultConfig.repo,
|
||||||
|
defaultConfig.branch,
|
||||||
|
token
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getGitHubConfig() {
|
function getGitHubConfig() {
|
||||||
const githubConfig = JSON.parse(localStorage.getItem("githubConfig"));
|
const githubConfig = JSON.parse(localStorage.getItem("githubConfig"));
|
||||||
const repoUrl = githubConfig.repo.replace("https://github.com/", "").replace("http://github.com/", "").replace("github.com/", "").split("/");
|
const repoUrl = githubConfig.repo
|
||||||
|
.replace("https://github.com/", "")
|
||||||
|
.replace("http://github.com/", "")
|
||||||
|
.replace("github.com/", "")
|
||||||
|
.split("/");
|
||||||
const username = repoUrl[0];
|
const username = repoUrl[0];
|
||||||
const repo = repoUrl[1];
|
const repo = repoUrl[1];
|
||||||
return getGitHubCommonConfig(username, repo, githubConfig.branch, githubConfig.accessToken);
|
return getGitHubCommonConfig(
|
||||||
|
username,
|
||||||
|
repo,
|
||||||
|
githubConfig.branch,
|
||||||
|
githubConfig.accessToken
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function ghFileUpload(content, filename) {
|
async function ghFileUpload(content, filename) {
|
||||||
const isDefault = localStorage.getItem('imgHost') !== 'github';
|
const isDefault = localStorage.getItem("imgHost") !== "github";
|
||||||
const config = isDefault ? getDefaultConfig() : getGitHubConfig();
|
const config = isDefault ? getDefaultConfig() : getGitHubConfig();
|
||||||
const dateFilename = new Date().getTime() + '-' + uuidv4() + '.' + filename.split('.')[1];
|
const dateFilename =
|
||||||
|
new Date().getTime() + "-" + uuidv4() + "." + filename.split(".")[1];
|
||||||
const res = await fetch({
|
const res = await fetch({
|
||||||
url: config.url + dateFilename,
|
url: config.url + dateFilename,
|
||||||
method: config.method,
|
method: config.method,
|
||||||
headers: config.headers,
|
headers: config.headers,
|
||||||
data: {
|
data: {
|
||||||
branch: config.branch || 'master',
|
branch: config.branch || "master",
|
||||||
message: `Upload by ${window.location.href}`,
|
message: `Upload by ${window.location.href}`,
|
||||||
content: content
|
content: content,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
const githubResourceUrl = 'raw.githubusercontent.com/filess/images/master/';
|
const githubResourceUrl = "raw.githubusercontent.com/filess/images/master/";
|
||||||
const cdnResourceUrl = 'cdn.jsdelivr.net/gh/filess/images/';
|
const cdnResourceUrl = "cdn.jsdelivr.net/gh/filess/images/";
|
||||||
return isDefault ? res.content.download_url.replace(githubResourceUrl, cdnResourceUrl) : res.content.download_url;
|
return isDefault
|
||||||
|
? res.content.download_url.replace(githubResourceUrl, cdnResourceUrl)
|
||||||
|
: res.content.download_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function aliOSSFileUpload(content, filename) {
|
async function aliOSSFileUpload(content, filename) {
|
||||||
const dateFilename = new Date().getTime() + '-' + uuidv4() + '.' + filename.split('.')[1];
|
const dateFilename =
|
||||||
const aliOSSConfig = JSON.parse(localStorage.getItem('aliOSSConfig'));
|
new Date().getTime() + "-" + uuidv4() + "." + filename.split(".")[1];
|
||||||
const buffer = Buffer(content, 'base64');
|
const aliOSSConfig = JSON.parse(localStorage.getItem("aliOSSConfig"));
|
||||||
|
const buffer = Buffer(content, "base64");
|
||||||
try {
|
try {
|
||||||
const dir = aliOSSConfig.path + '/' + dateFilename;
|
const dir = aliOSSConfig.path + "/" + dateFilename;
|
||||||
const client = new OSS({
|
const client = new OSS({
|
||||||
region: aliOSSConfig.region,
|
region: aliOSSConfig.region,
|
||||||
bucket: aliOSSConfig.bucket,
|
bucket: aliOSSConfig.bucket,
|
||||||
accessKeyId: aliOSSConfig.accessKeyId,
|
accessKeyId: aliOSSConfig.accessKeyId,
|
||||||
accessKeySecret: aliOSSConfig.accessKeySecret
|
accessKeySecret: aliOSSConfig.accessKeySecret,
|
||||||
});
|
});
|
||||||
const res = await client.put(dir, buffer);
|
const res = await client.put(dir, buffer);
|
||||||
return aliOSSConfig.cdnHost == '' ? res.url : aliOSSConfig.cdnHost + '/' + (aliOSSConfig.path == '' ? dateFilename : dir);
|
return aliOSSConfig.cdnHost == ""
|
||||||
|
? res.url
|
||||||
|
: aliOSSConfig.cdnHost +
|
||||||
|
"/" +
|
||||||
|
(aliOSSConfig.path == "" ? dateFilename : dir);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return Promise.reject(e);
|
return Promise.reject(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function txCOSFileUpload(file) {
|
async function txCOSFileUpload(file) {
|
||||||
const dateFilename = new Date().getTime() + '-' + uuidv4() + '.' + file.name.split('.')[1];
|
const dateFilename =
|
||||||
const txCOSConfig = JSON.parse(localStorage.getItem('txCOSConfig'));
|
new Date().getTime() + "-" + uuidv4() + "." + file.name.split(".")[1];
|
||||||
|
const txCOSConfig = JSON.parse(localStorage.getItem("txCOSConfig"));
|
||||||
const cos = new COS({
|
const cos = new COS({
|
||||||
SecretId: txCOSConfig.secretId,
|
SecretId: txCOSConfig.secretId,
|
||||||
SecretKey: txCOSConfig.secretKey
|
SecretKey: txCOSConfig.secretKey,
|
||||||
});
|
});
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
cos.putObject({
|
cos.putObject(
|
||||||
|
{
|
||||||
Bucket: txCOSConfig.bucket,
|
Bucket: txCOSConfig.bucket,
|
||||||
Region: txCOSConfig.region,
|
Region: txCOSConfig.region,
|
||||||
Key: txCOSConfig.path + '/' + dateFilename,
|
Key: txCOSConfig.path + "/" + dateFilename,
|
||||||
Body: file
|
Body: file,
|
||||||
}, function (err, data) {
|
},
|
||||||
|
function (err, data) {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
} else if (txCOSConfig.cdnHost) {
|
} else if (txCOSConfig.cdnHost) {
|
||||||
// if cdnHost exists
|
// if cdnHost exists
|
||||||
resolve(txCOSConfig.path != '' ? txCOSConfig.cdnHost + '/' + txCOSConfig.path + '/' + dateFilename : txCOSConfig.cdnHost + '/' + dateFilename);
|
resolve(
|
||||||
|
txCOSConfig.path != ""
|
||||||
|
? txCOSConfig.cdnHost +
|
||||||
|
"/" +
|
||||||
|
txCOSConfig.path +
|
||||||
|
"/" +
|
||||||
|
dateFilename
|
||||||
|
: txCOSConfig.cdnHost + "/" + dateFilename
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// if cdnHost not exists
|
// if cdnHost not exists
|
||||||
reject(data.Location);
|
reject(data.Location);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
fileUpload
|
fileUpload,
|
||||||
};
|
};
|
||||||
|
@ -6,12 +6,16 @@ import CodeMirror from "codemirror/lib/codemirror";
|
|||||||
pairs: "()[]{}''\"\"",
|
pairs: "()[]{}''\"\"",
|
||||||
closeBefore: ")]}'\":;>",
|
closeBefore: ")]}'\":;>",
|
||||||
triples: "",
|
triples: "",
|
||||||
explode: "[]{}"
|
explode: "[]{}",
|
||||||
};
|
};
|
||||||
|
|
||||||
var Pos = CodeMirror.Pos;
|
var Pos = CodeMirror.Pos;
|
||||||
|
|
||||||
CodeMirror.defineOption("autoCloseBrackets", false, function (cm, val, old) {
|
CodeMirror.defineOption("autoCloseBrackets", false, function (
|
||||||
|
cm,
|
||||||
|
val,
|
||||||
|
old
|
||||||
|
) {
|
||||||
if (old && old != CodeMirror.Init) {
|
if (old && old != CodeMirror.Init) {
|
||||||
cm.removeKeyMap(keyMap);
|
cm.removeKeyMap(keyMap);
|
||||||
cm.state.closeBrackets = null;
|
cm.state.closeBrackets = null;
|
||||||
@ -31,7 +35,7 @@ import CodeMirror from "codemirror/lib/codemirror";
|
|||||||
|
|
||||||
var keyMap = {
|
var keyMap = {
|
||||||
Backspace: handleBackspace,
|
Backspace: handleBackspace,
|
||||||
Enter: handleEnter
|
Enter: handleEnter,
|
||||||
};
|
};
|
||||||
|
|
||||||
function ensureBound(chars) {
|
function ensureBound(chars) {
|
||||||
@ -65,7 +69,8 @@ import CodeMirror from "codemirror/lib/codemirror";
|
|||||||
for (var i = 0; i < ranges.length; i++) {
|
for (var i = 0; i < ranges.length; i++) {
|
||||||
if (!ranges[i].empty()) return CodeMirror.Pass;
|
if (!ranges[i].empty()) return CodeMirror.Pass;
|
||||||
var around = charsAround(cm, ranges[i].head);
|
var around = charsAround(cm, ranges[i].head);
|
||||||
if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
|
if (!around || pairs.indexOf(around) % 2 != 0)
|
||||||
|
return CodeMirror.Pass;
|
||||||
}
|
}
|
||||||
for (var i = ranges.length - 1; i >= 0; i--) {
|
for (var i = ranges.length - 1; i >= 0; i--) {
|
||||||
var cur = ranges[i].head;
|
var cur = ranges[i].head;
|
||||||
@ -87,7 +92,8 @@ import CodeMirror from "codemirror/lib/codemirror";
|
|||||||
for (var i = 0; i < ranges.length; i++) {
|
for (var i = 0; i < ranges.length; i++) {
|
||||||
if (!ranges[i].empty()) return CodeMirror.Pass;
|
if (!ranges[i].empty()) return CodeMirror.Pass;
|
||||||
var around = charsAround(cm, ranges[i].head);
|
var around = charsAround(cm, ranges[i].head);
|
||||||
if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass;
|
if (!around || explode.indexOf(around) % 2 != 0)
|
||||||
|
return CodeMirror.Pass;
|
||||||
}
|
}
|
||||||
cm.operation(function () {
|
cm.operation(function () {
|
||||||
var linesep = cm.lineSeparator() || "\n";
|
var linesep = cm.lineSeparator() || "\n";
|
||||||
@ -105,8 +111,11 @@ import CodeMirror from "codemirror/lib/codemirror";
|
|||||||
function contractSelection(sel) {
|
function contractSelection(sel) {
|
||||||
var inverted = CodeMirror.cmpPos(sel.anchor, sel.head) > 0;
|
var inverted = CodeMirror.cmpPos(sel.anchor, sel.head) > 0;
|
||||||
return {
|
return {
|
||||||
anchor: new Pos(sel.anchor.line, sel.anchor.ch + (inverted ? -1 : 1)),
|
anchor: new Pos(
|
||||||
head: new Pos(sel.head.line, sel.head.ch + (inverted ? 1 : -1))
|
sel.anchor.line,
|
||||||
|
sel.anchor.ch + (inverted ? -1 : 1)
|
||||||
|
),
|
||||||
|
head: new Pos(sel.head.line, sel.head.ch + (inverted ? 1 : -1)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,13 +159,17 @@ import CodeMirror from "codemirror/lib/codemirror";
|
|||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
cur.ch > 2 &&
|
cur.ch > 2 &&
|
||||||
/\bstring/.test(cm.getTokenTypeAt(Pos(cur.line, cur.ch - 2)))
|
/\bstring/.test(
|
||||||
|
cm.getTokenTypeAt(Pos(cur.line, cur.ch - 2))
|
||||||
|
)
|
||||||
)
|
)
|
||||||
return CodeMirror.Pass;
|
return CodeMirror.Pass;
|
||||||
curType = "addFour";
|
curType = "addFour";
|
||||||
} else if (identical) {
|
} else if (identical) {
|
||||||
var prev =
|
var prev =
|
||||||
cur.ch == 0 ? " " : cm.getRange(Pos(cur.line, cur.ch - 1), cur);
|
cur.ch == 0
|
||||||
|
? " "
|
||||||
|
: cm.getRange(Pos(cur.line, cur.ch - 1), cur);
|
||||||
if (
|
if (
|
||||||
!CodeMirror.isWordChar(next) &&
|
!CodeMirror.isWordChar(next) &&
|
||||||
prev != ch &&
|
prev != ch &&
|
||||||
@ -166,7 +179,9 @@ import CodeMirror from "codemirror/lib/codemirror";
|
|||||||
else return CodeMirror.Pass;
|
else return CodeMirror.Pass;
|
||||||
} else if (
|
} else if (
|
||||||
opening &&
|
opening &&
|
||||||
(next.length === 0 || /\s/.test(next) || closeBefore.indexOf(next) > -1)
|
(next.length === 0 ||
|
||||||
|
/\s/.test(next) ||
|
||||||
|
closeBefore.indexOf(next) > -1)
|
||||||
) {
|
) {
|
||||||
curType = "both";
|
curType = "both";
|
||||||
} else {
|
} else {
|
||||||
@ -185,7 +200,8 @@ import CodeMirror from "codemirror/lib/codemirror";
|
|||||||
for (var i = 0; i < 3; i++) cm.execCommand("goCharRight");
|
for (var i = 0; i < 3; i++) cm.execCommand("goCharRight");
|
||||||
} else if (type == "surround") {
|
} else if (type == "surround") {
|
||||||
var sels = cm.getSelections();
|
var sels = cm.getSelections();
|
||||||
for (var i = 0; i < sels.length; i++) sels[i] = left + sels[i] + right;
|
for (var i = 0; i < sels.length; i++)
|
||||||
|
sels[i] = left + sels[i] + right;
|
||||||
cm.replaceSelections(sels, "around");
|
cm.replaceSelections(sels, "around");
|
||||||
sels = cm.listSelections().slice();
|
sels = cm.listSelections().slice();
|
||||||
for (var i = 0; i < sels.length; i++)
|
for (var i = 0; i < sels.length; i++)
|
||||||
@ -203,7 +219,10 @@ import CodeMirror from "codemirror/lib/codemirror";
|
|||||||
}
|
}
|
||||||
|
|
||||||
function charsAround(cm, pos) {
|
function charsAround(cm, pos) {
|
||||||
var str = cm.getRange(Pos(pos.line, pos.ch - 1), Pos(pos.line, pos.ch + 1));
|
var str = cm.getRange(
|
||||||
|
Pos(pos.line, pos.ch - 1),
|
||||||
|
Pos(pos.line, pos.ch + 1)
|
||||||
|
);
|
||||||
return str.length == 2 ? str : null;
|
return str.length == 2 ? str : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,69 +1,74 @@
|
|||||||
export default {
|
export default {
|
||||||
builtinFonts: [{
|
builtinFonts: [
|
||||||
label: '无衬线',
|
{
|
||||||
value: '-apple-system-font,BlinkMacSystemFont, Helvetica Neue, PingFang SC, Hiragino Sans GB , Microsoft YaHei UI , Microsoft YaHei ,Arial,sans-serif'
|
label: "无衬线",
|
||||||
|
value:
|
||||||
|
"-apple-system-font,BlinkMacSystemFont, Helvetica Neue, PingFang SC, Hiragino Sans GB , Microsoft YaHei UI , Microsoft YaHei ,Arial,sans-serif",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '衬线',
|
label: "衬线",
|
||||||
value: "Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, 'PingFang SC', Cambria, Cochin, Georgia, Times, 'Times New Roman', serif"
|
value:
|
||||||
}
|
"Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, 'PingFang SC', Cambria, Cochin, Georgia, Times, 'Times New Roman', serif",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
sizeOption: [{
|
sizeOption: [
|
||||||
label: '12px',
|
{
|
||||||
value: '12px',
|
label: "12px",
|
||||||
desc: '更小'
|
value: "12px",
|
||||||
|
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: '经典蓝',
|
{
|
||||||
value: 'rgba(15, 76, 129, 1)',
|
label: "经典蓝",
|
||||||
desc: '最新流行'
|
value: "rgba(15, 76, 129, 1)",
|
||||||
|
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: '微信',
|
label: "微信",
|
||||||
value: 'wechat',
|
value: "wechat",
|
||||||
desc: '默认样式'
|
desc: "默认样式",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'GitHub',
|
label: "GitHub",
|
||||||
value: 'github',
|
value: "github",
|
||||||
desc: '精简风格'
|
desc: "精简风格",
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
form: {
|
form: {
|
||||||
rows: 1,
|
rows: 1,
|
||||||
cols: 1
|
cols: 1,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
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];
|
||||||
@ -15,13 +15,11 @@ export function solveWeChatImage() {
|
|||||||
}
|
}
|
||||||
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(
|
res = juice.inlineContent(html, {
|
||||||
html, {
|
|
||||||
inlinePseudoElements: true,
|
inlinePseudoElements: true,
|
||||||
preserveImportant: true
|
preserveImportant: true,
|
||||||
}
|
});
|
||||||
);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
const DEFAULT_CONTENT =
|
const DEFAULT_CONTENT = `# 示例文章:Google 搜索的即时自动补全功能究竟是如何“工作”的?
|
||||||
`# 示例文章:Google 搜索的即时自动补全功能究竟是如何“工作”的?
|
|
||||||
> Google 搜索**自动补全功能**的强大,相信不少朋友都能感受到,它帮助我们更快地“补全”我们所要输入的搜索关键字。那么,它怎么知道我们要输入什么内容?它又是如何工作的?在这篇文章里,我们一起来看看。
|
> Google 搜索**自动补全功能**的强大,相信不少朋友都能感受到,它帮助我们更快地“补全”我们所要输入的搜索关键字。那么,它怎么知道我们要输入什么内容?它又是如何工作的?在这篇文章里,我们一起来看看。
|
||||||
|
|
||||||
## 使用自动补全
|
## 使用自动补全
|
||||||
@ -96,5 +95,5 @@ Google 拥有专门设计的系统,可以自动捕获不适当的预测结果
|
|||||||
<img src="https://gitee.com/yanglbme/resource/raw/master/doocs-md/qrcode.png" style="width: 100px;">
|
<img src="https://gitee.com/yanglbme/resource/raw/master/doocs-md/qrcode.png" style="width: 100px;">
|
||||||
</center>
|
</center>
|
||||||
|
|
||||||
`
|
`;
|
||||||
export default DEFAULT_CONTENT
|
export default DEFAULT_CONTENT;
|
||||||
|
@ -1,96 +1,120 @@
|
|||||||
import CodeMirror from "codemirror/lib/codemirror";
|
import CodeMirror from "codemirror/lib/codemirror";
|
||||||
(function () {
|
(function () {
|
||||||
CodeMirror.extendMode('css', {
|
CodeMirror.extendMode("css", {
|
||||||
commentStart: '/*',
|
commentStart: "/*",
|
||||||
commentEnd: '*/',
|
commentEnd: "*/",
|
||||||
newlineAfterToken: function (type, content) {
|
newlineAfterToken: function (type, content) {
|
||||||
return /^[;{}]$/.test(content)
|
return /^[;{}]$/.test(content);
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
// Comment/uncomment the specified range
|
// Comment/uncomment the specified range
|
||||||
CodeMirror.defineExtension('commentRange', function (isComment, from, to) {
|
CodeMirror.defineExtension("commentRange", function (isComment, from, to) {
|
||||||
var cm = this;
|
var cm = this;
|
||||||
var curMode = CodeMirror.innerMode(cm.getMode(), cm.getTokenAt(from).state).mode
|
var curMode = CodeMirror.innerMode(
|
||||||
|
cm.getMode(),
|
||||||
|
cm.getTokenAt(from).state
|
||||||
|
).mode;
|
||||||
cm.operation(function () {
|
cm.operation(function () {
|
||||||
if (isComment) { // Comment range
|
if (isComment) {
|
||||||
cm.replaceRange(curMode.commentEnd, to)
|
// Comment range
|
||||||
cm.replaceRange(curMode.commentStart, from)
|
cm.replaceRange(curMode.commentEnd, to);
|
||||||
if (from.line == to.line && from.ch == to.ch) // An empty comment inserted - put cursor inside
|
cm.replaceRange(curMode.commentStart, from);
|
||||||
{
|
if (from.line == to.line && from.ch == to.ch) {
|
||||||
cm.setCursor(from.line, from.ch + curMode.commentStart.length)
|
// An empty comment inserted - put cursor inside
|
||||||
|
cm.setCursor(
|
||||||
|
from.line,
|
||||||
|
from.ch + curMode.commentStart.length
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else { // Uncomment range
|
} else {
|
||||||
var selText = cm.getRange(from, to)
|
// Uncomment range
|
||||||
var startIndex = selText.indexOf(curMode.commentStart)
|
var selText = cm.getRange(from, to);
|
||||||
var endIndex = selText.lastIndexOf(curMode.commentEnd)
|
var startIndex = selText.indexOf(curMode.commentStart);
|
||||||
|
var endIndex = selText.lastIndexOf(curMode.commentEnd);
|
||||||
if (startIndex > -1 && endIndex > -1 && endIndex > startIndex) {
|
if (startIndex > -1 && endIndex > -1 && endIndex > startIndex) {
|
||||||
// Take string till comment start
|
// Take string till comment start
|
||||||
selText = selText.substr(0, startIndex) +
|
selText =
|
||||||
|
selText.substr(0, startIndex) +
|
||||||
// From comment start till comment end
|
// From comment start till comment end
|
||||||
selText.substring(startIndex + curMode.commentStart.length, endIndex) +
|
selText.substring(
|
||||||
|
startIndex + curMode.commentStart.length,
|
||||||
|
endIndex
|
||||||
|
) +
|
||||||
// From comment end till string end
|
// From comment end till string end
|
||||||
selText.substr(endIndex + curMode.commentEnd.length)
|
selText.substr(endIndex + curMode.commentEnd.length);
|
||||||
}
|
}
|
||||||
cm.replaceRange(selText, from, to)
|
cm.replaceRange(selText, from, to);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
// Applies automatic mode-aware indentation to the specified range
|
// Applies automatic mode-aware indentation to the specified range
|
||||||
CodeMirror.defineExtension('autoIndentRange', function (from, to) {
|
CodeMirror.defineExtension("autoIndentRange", function (from, to) {
|
||||||
var cmInstance = this
|
var cmInstance = this;
|
||||||
this.operation(function () {
|
this.operation(function () {
|
||||||
for (var i = from.line; i <= to.line; i++) {
|
for (var i = from.line; i <= to.line; i++) {
|
||||||
cmInstance.indentLine(i, 'smart')
|
cmInstance.indentLine(i, "smart");
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
// Applies automatic formatting to the specified range
|
// Applies automatic formatting to the specified range
|
||||||
CodeMirror.defineExtension('autoFormatRange', function (from, to) {
|
CodeMirror.defineExtension("autoFormatRange", function (from, to) {
|
||||||
var cm = this
|
var cm = this;
|
||||||
var outer = cm.getMode();
|
var outer = cm.getMode();
|
||||||
var text = cm.getRange(from, to).split('\n')
|
var text = cm.getRange(from, to).split("\n");
|
||||||
var state = CodeMirror.copyState(outer, cm.getTokenAt(from).state)
|
var state = CodeMirror.copyState(outer, cm.getTokenAt(from).state);
|
||||||
var tabSize = cm.getOption('tabSize')
|
var tabSize = cm.getOption("tabSize");
|
||||||
|
|
||||||
var out = '';
|
var out = "";
|
||||||
var lines = 0;
|
var lines = 0;
|
||||||
var atSol = from.ch == 0
|
var atSol = from.ch == 0;
|
||||||
|
|
||||||
function newline() {
|
function newline() {
|
||||||
out += '\n'
|
out += "\n";
|
||||||
atSol = true
|
atSol = true;
|
||||||
++lines
|
++lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < text.length; ++i) {
|
for (var i = 0; i < text.length; ++i) {
|
||||||
var stream = new CodeMirror.StringStream(text[i], tabSize)
|
var stream = new CodeMirror.StringStream(text[i], tabSize);
|
||||||
while (!stream.eol()) {
|
while (!stream.eol()) {
|
||||||
var inner = CodeMirror.innerMode(outer, state)
|
var inner = CodeMirror.innerMode(outer, state);
|
||||||
var style = outer.token(stream, state);
|
var style = outer.token(stream, state);
|
||||||
var cur = stream.current()
|
var cur = stream.current();
|
||||||
stream.start = stream.pos
|
stream.start = stream.pos;
|
||||||
if (!atSol || /\S/.test(cur)) {
|
if (!atSol || /\S/.test(cur)) {
|
||||||
out += cur
|
out += cur;
|
||||||
atSol = false
|
atSol = false;
|
||||||
}
|
}
|
||||||
if (!atSol && inner.mode.newlineAfterToken &&
|
if (
|
||||||
inner.mode.newlineAfterToken(style, cur, stream.string.slice(stream.pos) || text[i + 1] || '', inner.state)) {
|
!atSol &&
|
||||||
newline()
|
inner.mode.newlineAfterToken &&
|
||||||
|
inner.mode.newlineAfterToken(
|
||||||
|
style,
|
||||||
|
cur,
|
||||||
|
stream.string.slice(stream.pos) || text[i + 1] || "",
|
||||||
|
inner.state
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
newline();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!stream.pos && outer.blankLine) outer.blankLine(state)
|
if (!stream.pos && outer.blankLine) outer.blankLine(state);
|
||||||
if (!atSol) newline()
|
if (!atSol) newline();
|
||||||
}
|
}
|
||||||
|
|
||||||
cm.operation(function () {
|
cm.operation(function () {
|
||||||
cm.replaceRange(out, from, to)
|
cm.replaceRange(out, from, to);
|
||||||
for (var cur = from.line + 1, end = from.line + lines; cur <= end; ++cur) {
|
for (
|
||||||
cm.indentLine(cur, 'smart')
|
var cur = from.line + 1, end = from.line + lines;
|
||||||
|
cur <= end;
|
||||||
|
++cur
|
||||||
|
) {
|
||||||
|
cm.indentLine(cur, "smart");
|
||||||
}
|
}
|
||||||
cm.setSelection(from, cm.getCursor(false))
|
cm.setSelection(from, cm.getCursor(false));
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})()
|
})();
|
||||||
|
@ -1,66 +1,69 @@
|
|||||||
import marked from 'marked';
|
import marked from "marked";
|
||||||
const WxRenderer = function (opts) {
|
const WxRenderer = function (opts) {
|
||||||
this.opts = opts
|
this.opts = opts;
|
||||||
let ENV_STRETCH_IMAGE = true
|
let ENV_STRETCH_IMAGE = true;
|
||||||
|
|
||||||
let footnotes = []
|
let footnotes = [];
|
||||||
let footnoteIndex = 0
|
let footnoteIndex = 0;
|
||||||
let styleMapping = null
|
let styleMapping = null;
|
||||||
|
|
||||||
const CODE_FONT_FAMILY = 'Menlo, Operator Mono, Consolas, Monaco, monospace'
|
const CODE_FONT_FAMILY =
|
||||||
|
"Menlo, Operator Mono, Consolas, Monaco, monospace";
|
||||||
|
|
||||||
let merge = (base, extend) => Object.assign({}, base, extend)
|
let merge = (base, extend) => Object.assign({}, base, extend);
|
||||||
|
|
||||||
this.buildTheme = themeTpl => {
|
this.buildTheme = (themeTpl) => {
|
||||||
let mapping = {}
|
let mapping = {};
|
||||||
let base = merge(themeTpl.BASE, {
|
let base = merge(themeTpl.BASE, {
|
||||||
'font-family': this.opts.fonts,
|
"font-family": this.opts.fonts,
|
||||||
'font-size': this.opts.size
|
"font-size": this.opts.size,
|
||||||
})
|
});
|
||||||
let base_block = merge(base, {})
|
let base_block = merge(base, {});
|
||||||
for (let ele in themeTpl.inline) {
|
for (let ele in themeTpl.inline) {
|
||||||
if (themeTpl.inline.hasOwnProperty(ele)) {
|
if (themeTpl.inline.hasOwnProperty(ele)) {
|
||||||
let style = themeTpl.inline[ele]
|
let style = themeTpl.inline[ele];
|
||||||
mapping[ele] = merge(base, style)
|
mapping[ele] = merge(base, style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let ele in themeTpl.block) {
|
for (let ele in themeTpl.block) {
|
||||||
if (themeTpl.block.hasOwnProperty(ele)) {
|
if (themeTpl.block.hasOwnProperty(ele)) {
|
||||||
let style = themeTpl.block[ele]
|
let style = themeTpl.block[ele];
|
||||||
if (ele === 'code') {
|
if (ele === "code") {
|
||||||
style['font-family'] = CODE_FONT_FAMILY
|
style["font-family"] = CODE_FONT_FAMILY;
|
||||||
}
|
}
|
||||||
mapping[ele] = merge(base_block, style)
|
mapping[ele] = merge(base_block, style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mapping
|
return mapping;
|
||||||
}
|
};
|
||||||
|
|
||||||
let getStyles = (tokenName, addition) => {
|
let getStyles = (tokenName, addition) => {
|
||||||
let arr = []
|
let arr = [];
|
||||||
let dict = styleMapping[tokenName]
|
let dict = styleMapping[tokenName];
|
||||||
if (!dict) return ''
|
if (!dict) return "";
|
||||||
for (const key in dict) {
|
for (const key in dict) {
|
||||||
arr.push(key + ':' + dict[key])
|
arr.push(key + ":" + dict[key]);
|
||||||
}
|
|
||||||
return `style="${arr.join(';') + (addition || '')}"`
|
|
||||||
}
|
}
|
||||||
|
return `style="${arr.join(";") + (addition || "")}"`;
|
||||||
|
};
|
||||||
|
|
||||||
let addFootnote = (title, link) => {
|
let addFootnote = (title, link) => {
|
||||||
footnotes.push([++footnoteIndex, title, link])
|
footnotes.push([++footnoteIndex, title, link]);
|
||||||
return footnoteIndex
|
return footnoteIndex;
|
||||||
}
|
};
|
||||||
|
|
||||||
this.buildFootnotes = () => {
|
this.buildFootnotes = () => {
|
||||||
let footnoteArray = footnotes.map(x => {
|
let footnoteArray = footnotes.map((x) => {
|
||||||
if (x[1] === x[2]) {
|
if (x[1] === x[2]) {
|
||||||
return `<code style="font-size: 90%; opacity: 0.6;">[${x[0]}]</code>: <i>${x[1]}</i><br/>`
|
return `<code style="font-size: 90%; opacity: 0.6;">[${x[0]}]</code>: <i>${x[1]}</i><br/>`;
|
||||||
}
|
|
||||||
return `<code style="font-size: 90%; opacity: 0.6;">[${x[0]}]</code> ${x[1]}: <i>${x[2]}</i><br/>`
|
|
||||||
})
|
|
||||||
return `<h4 ${getStyles('h4')}>引用链接</h4><p ${getStyles('footnotes')}>${footnoteArray.join('\n')}</p>`
|
|
||||||
}
|
}
|
||||||
|
return `<code style="font-size: 90%; opacity: 0.6;">[${x[0]}]</code> ${x[1]}: <i>${x[2]}</i><br/>`;
|
||||||
|
});
|
||||||
|
return `<h4 ${getStyles("h4")}>引用链接</h4><p ${getStyles(
|
||||||
|
"footnotes"
|
||||||
|
)}>${footnoteArray.join("\n")}</p>`;
|
||||||
|
};
|
||||||
|
|
||||||
this.buildAddition = () => {
|
this.buildAddition = () => {
|
||||||
return `
|
return `
|
||||||
@ -78,99 +81,129 @@ const WxRenderer = function (opts) {
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
`
|
`;
|
||||||
}
|
};
|
||||||
|
|
||||||
this.setOptions = newOpts => {
|
this.setOptions = (newOpts) => {
|
||||||
this.opts = merge(this.opts, newOpts)
|
this.opts = merge(this.opts, newOpts);
|
||||||
}
|
};
|
||||||
|
|
||||||
this.hasFootnotes = () => footnotes.length !== 0
|
this.hasFootnotes = () => footnotes.length !== 0;
|
||||||
|
|
||||||
this.getRenderer = (status) => {
|
this.getRenderer = (status) => {
|
||||||
footnotes = []
|
footnotes = [];
|
||||||
footnoteIndex = 0
|
footnoteIndex = 0;
|
||||||
|
|
||||||
styleMapping = this.buildTheme(this.opts.theme)
|
styleMapping = this.buildTheme(this.opts.theme);
|
||||||
let renderer = new marked.Renderer()
|
let renderer = new marked.Renderer();
|
||||||
|
|
||||||
renderer.heading = (text, level) => {
|
renderer.heading = (text, level) => {
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case 1:
|
case 1:
|
||||||
return `<h1 ${getStyles('h1')}>${text}</h1>`
|
return `<h1 ${getStyles("h1")}>${text}</h1>`;
|
||||||
case 2:
|
case 2:
|
||||||
return `<h2 ${getStyles('h2')}>${text}</h2>`
|
return `<h2 ${getStyles("h2")}>${text}</h2>`;
|
||||||
case 3:
|
case 3:
|
||||||
return `<h3 ${getStyles('h3')}>${text}</h3>`
|
return `<h3 ${getStyles("h3")}>${text}</h3>`;
|
||||||
default:
|
default:
|
||||||
return `<h4 ${getStyles('h4')}>${text}</h4>`
|
return `<h4 ${getStyles("h4")}>${text}</h4>`;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
renderer.paragraph = text => {
|
renderer.paragraph = (text) => {
|
||||||
if (text.indexOf('<figure') != -1 && text.indexOf('<img') != -1) {
|
if (text.indexOf("<figure") != -1 && text.indexOf("<img") != -1) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
return text.replace(/ /g, '') === '' ? '' : `<p ${getStyles('p')}>${text}</p>`
|
return text.replace(/ /g, "") === ""
|
||||||
}
|
? ""
|
||||||
|
: `<p ${getStyles("p")}>${text}</p>`;
|
||||||
|
};
|
||||||
|
|
||||||
renderer.blockquote = text => {
|
renderer.blockquote = (text) => {
|
||||||
text = text.replace(/<p.*?>/g, `<p ${getStyles('blockquote_p')}>`)
|
text = text.replace(/<p.*?>/g, `<p ${getStyles("blockquote_p")}>`);
|
||||||
return `<blockquote ${getStyles('blockquote')}>${text}</blockquote>`
|
return `<blockquote ${getStyles(
|
||||||
}
|
"blockquote"
|
||||||
|
)}>${text}</blockquote>`;
|
||||||
|
};
|
||||||
renderer.code = (text, lang) => {
|
renderer.code = (text, lang) => {
|
||||||
text = text.replace(/</g, '<').replace(/>/g, '>')
|
text = text.replace(/</g, "<").replace(/>/g, ">");
|
||||||
const codeLines = text.split('\n').map(line => `<code class="prettyprint"><span class="code-snippet_outer">${(line || '<br>')}</span></code>`)
|
const codeLines = text
|
||||||
const codeTheme = 'github'
|
.split("\n")
|
||||||
|
.map(
|
||||||
|
(line) =>
|
||||||
|
`<code class="prettyprint"><span class="code-snippet_outer">${
|
||||||
|
line || "<br>"
|
||||||
|
}</span></code>`
|
||||||
|
);
|
||||||
|
const codeTheme = "github";
|
||||||
return `
|
return `
|
||||||
<section class="code-snippet__${codeTheme}">
|
<section class="code-snippet__${codeTheme}">
|
||||||
<pre class="code__pre" data-lang="${lang}">
|
<pre class="code__pre" data-lang="${lang}">
|
||||||
${codeLines.join('')}
|
${codeLines.join("")}
|
||||||
</pre>
|
</pre>
|
||||||
</section>
|
</section>
|
||||||
`
|
`;
|
||||||
}
|
};
|
||||||
renderer.codespan = (text, lang) => `<code ${getStyles('codespan')}>${text}</code>`
|
renderer.codespan = (text, lang) =>
|
||||||
renderer.listitem = text => `<span ${getStyles('listitem')}><span style="margin-right: 10px;"><%s/></span>${text}</span>`
|
`<code ${getStyles("codespan")}>${text}</code>`;
|
||||||
|
renderer.listitem = (text) =>
|
||||||
|
`<span ${getStyles(
|
||||||
|
"listitem"
|
||||||
|
)}><span style="margin-right: 10px;"><%s/></span>${text}</span>`;
|
||||||
|
|
||||||
renderer.list = (text, ordered, start) => {
|
renderer.list = (text, ordered, start) => {
|
||||||
text = text.replace(/<\/*p.*?>/g, '')
|
text = text.replace(/<\/*p.*?>/g, "");
|
||||||
let segments = text.split(`<%s/>`)
|
let segments = text.split(`<%s/>`);
|
||||||
if (!ordered) {
|
if (!ordered) {
|
||||||
text = segments.join('•')
|
text = segments.join("•");
|
||||||
return `<p ${getStyles('ul')}>${text}</p>`
|
return `<p ${getStyles("ul")}>${text}</p>`;
|
||||||
}
|
}
|
||||||
text = segments[0]
|
text = segments[0];
|
||||||
for (let i = 1; i < segments.length; i++) {
|
for (let i = 1; i < segments.length; i++) {
|
||||||
text = text + i + '.' + segments[i]
|
text = text + i + "." + segments[i];
|
||||||
}
|
|
||||||
return `<p ${getStyles('ol')}>${text}</p>`
|
|
||||||
}
|
}
|
||||||
|
return `<p ${getStyles("ol")}>${text}</p>`;
|
||||||
|
};
|
||||||
renderer.image = (href, title, text) => {
|
renderer.image = (href, title, text) => {
|
||||||
let subText = ''
|
let subText = "";
|
||||||
if (text) {
|
if (text) {
|
||||||
subText = `<figcaption ${getStyles('figcaption')}>${text}</figcaption>`
|
subText = `<figcaption ${getStyles(
|
||||||
}
|
"figcaption"
|
||||||
let figureStyles = getStyles('figure')
|
)}>${text}</figcaption>`;
|
||||||
let imgStyles = getStyles(ENV_STRETCH_IMAGE ? 'image' : 'image_org')
|
|
||||||
return `<figure ${figureStyles}><img ${imgStyles} src="${href}" title="${title}" alt="${text}"/>${subText}</figure>`
|
|
||||||
}
|
}
|
||||||
|
let figureStyles = getStyles("figure");
|
||||||
|
let imgStyles = getStyles(
|
||||||
|
ENV_STRETCH_IMAGE ? "image" : "image_org"
|
||||||
|
);
|
||||||
|
return `<figure ${figureStyles}><img ${imgStyles} src="${href}" title="${title}" alt="${text}"/>${subText}</figure>`;
|
||||||
|
};
|
||||||
renderer.link = (href, title, text) => {
|
renderer.link = (href, title, text) => {
|
||||||
if (href.indexOf('https://mp.weixin.qq.com') === 0) {
|
if (href.indexOf("https://mp.weixin.qq.com") === 0) {
|
||||||
return `<a href="${href}" title="${(title || text)}" ${getStyles('wx_link')}>${text}</a>`
|
return `<a href="${href}" title="${title || text}" ${getStyles(
|
||||||
|
"wx_link"
|
||||||
|
)}>${text}</a>`;
|
||||||
}
|
}
|
||||||
if (href === text || !status) {
|
if (href === text || !status) {
|
||||||
return text
|
return text;
|
||||||
}
|
}
|
||||||
let ref = addFootnote(title || text, href)
|
let ref = addFootnote(title || text, href);
|
||||||
return `<span ${getStyles('link')}>${text}<sup>[${ref}]</sup></span>`
|
return `<span ${getStyles(
|
||||||
}
|
"link"
|
||||||
renderer.strong = text => `<strong ${getStyles('strong')}>${text}</strong>`
|
)}>${text}<sup>[${ref}]</sup></span>`;
|
||||||
renderer.em = text => `<span style="font-style: italic;">${text}</span>`
|
};
|
||||||
renderer.table = (header, body) => `<section style="padding:0 8px;"><table class="preview-table"><thead ${getStyles('thead')}>${header}</thead><tbody>${body}</tbody></table></section>`
|
renderer.strong = (text) =>
|
||||||
|
`<strong ${getStyles("strong")}>${text}</strong>`;
|
||||||
|
renderer.em = (text) =>
|
||||||
|
`<span style="font-style: italic;">${text}</span>`;
|
||||||
|
renderer.table = (header, body) =>
|
||||||
|
`<section style="padding:0 8px;"><table class="preview-table"><thead ${getStyles(
|
||||||
|
"thead"
|
||||||
|
)}>${header}</thead><tbody>${body}</tbody></table></section>`;
|
||||||
// renderer.tablerow = (text) => `<tr style="">${text}</tr>`;
|
// renderer.tablerow = (text) => `<tr style="">${text}</tr>`;
|
||||||
renderer.tablecell = (text, flags) => `<td ${getStyles('td')}>${text}</td>`
|
renderer.tablecell = (text, flags) =>
|
||||||
renderer.hr = () => `<hr style="border-style: solid;border-width: 1px 0 0;border-color: rgba(0,0,0,0.1);-webkit-transform-origin: 0 0;-webkit-transform: scale(1, 0.5);transform-origin: 0 0;transform: scale(1, 0.5);">`
|
`<td ${getStyles("td")}>${text}</td>`;
|
||||||
return renderer
|
renderer.hr = () =>
|
||||||
}
|
`<hr style="border-style: solid;border-width: 1px 0 0;border-color: rgba(0,0,0,0.1);-webkit-transform-origin: 0 0;-webkit-transform: scale(1, 0.5);transform-origin: 0 0;transform: scale(1, 0.5);">`;
|
||||||
}
|
return renderer;
|
||||||
export default WxRenderer
|
};
|
||||||
|
};
|
||||||
|
export default WxRenderer;
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
const DEFAULT_CSS_CONTENT =
|
const DEFAULT_CSS_CONTENT = `/*
|
||||||
`/*
|
|
||||||
按Ctrl+F可格式化
|
按Ctrl+F可格式化
|
||||||
*/
|
*/
|
||||||
/* 一级标题样式 */
|
/* 一级标题样式 */
|
||||||
@ -38,5 +37,5 @@ link {
|
|||||||
/* 微信链接样式 */
|
/* 微信链接样式 */
|
||||||
wx_link {
|
wx_link {
|
||||||
}
|
}
|
||||||
`
|
`;
|
||||||
export default DEFAULT_CSS_CONTENT
|
export default DEFAULT_CSS_CONTENT;
|
||||||
|
@ -1,178 +1,178 @@
|
|||||||
export default {
|
export default {
|
||||||
BASE: {
|
BASE: {
|
||||||
'text-align': 'left',
|
"text-align": "left",
|
||||||
'color': '#3f3f3f',
|
color: "#3f3f3f",
|
||||||
'line-height': '1.75',
|
"line-height": "1.75",
|
||||||
},
|
},
|
||||||
BASE_BLOCK: {
|
BASE_BLOCK: {
|
||||||
'margin': '1em 8px'
|
margin: "1em 8px",
|
||||||
},
|
},
|
||||||
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)",
|
||||||
},
|
},
|
||||||
|
|
||||||
// 二级标题样式
|
// 二级标题样式
|
||||||
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)",
|
||||||
},
|
},
|
||||||
|
|
||||||
// 四级标题样式
|
// 四级标题样式
|
||||||
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",
|
||||||
},
|
},
|
||||||
|
|
||||||
// 引用样式
|
// 引用样式
|
||||||
blockquote: {
|
blockquote: {
|
||||||
'font-style': 'normal',
|
"font-style": "normal",
|
||||||
'border-left': 'none',
|
"border-left": "none",
|
||||||
'padding': '1em',
|
padding: "1em",
|
||||||
'border-radius': '4px',
|
"border-radius": "4px",
|
||||||
'color': '#FEEEED',
|
color: "#FEEEED",
|
||||||
'background': 'rgba(27,31,35,.05)',
|
background: "rgba(27,31,35,.05)",
|
||||||
'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: {
|
code: {
|
||||||
'font-size': '80%',
|
"font-size": "80%",
|
||||||
'overflow': 'auto',
|
overflow: "auto",
|
||||||
'color': '#333',
|
color: "#333",
|
||||||
'white-space': 'pre',
|
"white-space": "pre",
|
||||||
'background': 'rgb(247, 247, 247)',
|
background: "rgb(247, 247, 247)",
|
||||||
'border-radius': '2px',
|
"border-radius": "2px",
|
||||||
'padding': '10px',
|
padding: "10px",
|
||||||
'line-height': '1.5',
|
"line-height": "1.5",
|
||||||
'border': '1px solid rgb(236,236,236)',
|
border: "1px solid rgb(236,236,236)",
|
||||||
'margin': '20px 0',
|
margin: "20px 0",
|
||||||
},
|
},
|
||||||
|
|
||||||
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",
|
||||||
},
|
},
|
||||||
|
|
||||||
image_org: {
|
image_org: {
|
||||||
'border-radius': '4px',
|
"border-radius": "4px",
|
||||||
'display': 'block'
|
display: "block",
|
||||||
},
|
},
|
||||||
|
|
||||||
ol: {
|
ol: {
|
||||||
'margin-left': '0',
|
"margin-left": "0",
|
||||||
'padding-left': '1em'
|
"padding-left": "1em",
|
||||||
},
|
},
|
||||||
|
|
||||||
ul: {
|
ul: {
|
||||||
'margin-left': '0',
|
"margin-left": "0",
|
||||||
'padding-left': '1em',
|
"padding-left": "1em",
|
||||||
'list-style': 'circle'
|
"list-style": "circle",
|
||||||
},
|
},
|
||||||
|
|
||||||
footnotes: {
|
footnotes: {
|
||||||
'margin': '0.5em 8px',
|
margin: "0.5em 8px",
|
||||||
'font-size': '80%'
|
"font-size": "80%",
|
||||||
},
|
},
|
||||||
|
|
||||||
figure: {
|
figure: {
|
||||||
'margin': '1.5em 8px',
|
margin: "1.5em 8px",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
inline: {
|
inline: {
|
||||||
listitem: {
|
listitem: {
|
||||||
'text-indent': '-1em',
|
"text-indent": "-1em",
|
||||||
'display': 'block',
|
display: "block",
|
||||||
'margin': '0.2em 8px'
|
margin: "0.2em 8px",
|
||||||
},
|
},
|
||||||
|
|
||||||
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",
|
||||||
},
|
},
|
||||||
|
|
||||||
thead: {
|
thead: {
|
||||||
'background': 'rgba(0, 0, 0, 0.05)',
|
background: "rgba(0, 0, 0, 0.05)",
|
||||||
'font-weight': 'bold'
|
"font-weight": "bold",
|
||||||
},
|
},
|
||||||
|
|
||||||
td: {
|
td: {
|
||||||
'border': '1px solid #dfdfdf',
|
border: "1px solid #dfdfdf",
|
||||||
'padding': '0.25em 0.5em'
|
padding: "0.25em 0.5em",
|
||||||
},
|
},
|
||||||
|
|
||||||
footnote: {
|
footnote: {
|
||||||
'font-size': '12px'
|
"font-size": "12px",
|
||||||
},
|
},
|
||||||
|
|
||||||
figcaption: {
|
figcaption: {
|
||||||
'text-align': 'center',
|
"text-align": "center",
|
||||||
'color': '#888',
|
color: "#888",
|
||||||
'font-size': '0.8em'
|
"font-size": "0.8em",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import fileApi from '../../api/file';
|
import fileApi from "../../api/file";
|
||||||
|
|
||||||
export function uploadImgFile(file) {
|
export function uploadImgFile(file) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -12,22 +12,25 @@ export function uploadImgFile(file) {
|
|||||||
|
|
||||||
base64Reader.readAsDataURL(file);
|
base64Reader.readAsDataURL(file);
|
||||||
base64Reader.onload = function () {
|
base64Reader.onload = function () {
|
||||||
const base64Content = this.result.split(',').pop();
|
const base64Content = this.result.split(",").pop();
|
||||||
fileApi.fileUpload(base64Content, file).then(res => {
|
fileApi
|
||||||
|
.fileUpload(base64Content, file)
|
||||||
|
.then((res) => {
|
||||||
resolve(res);
|
resolve(res);
|
||||||
}).catch(err => {
|
|
||||||
reject(err);
|
|
||||||
})
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isImageIllegal(file) {
|
export function isImageIllegal(file) {
|
||||||
if (!/\.(gif|jpg|jpeg|png|GIF|JPG|PNG)$/.test(file.name)) {
|
if (!/\.(gif|jpg|jpeg|png|GIF|JPG|PNG)$/.test(file.name)) {
|
||||||
return '请上传 JPG/PNG/GIF 格式的图片';
|
return "请上传 JPG/PNG/GIF 格式的图片";
|
||||||
}
|
}
|
||||||
if (file.size > 5 * 1024 * 1024) {
|
if (file.size > 5 * 1024 * 1024) {
|
||||||
return '由于公众号限制,图片大小不能超过 5.0M';
|
return "由于公众号限制,图片大小不能超过 5.0M";
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1,95 +1,94 @@
|
|||||||
import default_theme from './themes/default-theme'
|
import default_theme 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";
|
||||||
|
|
||||||
|
|
||||||
// 设置自定义颜色
|
// 设置自定义颜色
|
||||||
export function setColorWithTemplate(template) {
|
export function setColorWithTemplate(template) {
|
||||||
return function (color) {
|
return function (color) {
|
||||||
let custom_theme = JSON.parse(JSON.stringify(template))
|
let custom_theme = JSON.parse(JSON.stringify(template));
|
||||||
custom_theme.block.h1['border-bottom'] = `2px solid ${color}`
|
custom_theme.block.h1["border-bottom"] = `2px solid ${color}`;
|
||||||
custom_theme.block.h2['background'] = color
|
custom_theme.block.h2["background"] = color;
|
||||||
custom_theme.block.h3['border-left'] = `3px solid ${color}`
|
custom_theme.block.h3["border-left"] = `3px solid ${color}`;
|
||||||
custom_theme.block.h4['color'] = color
|
custom_theme.block.h4["color"] = color;
|
||||||
custom_theme.inline.strong['color'] = color
|
custom_theme.inline.strong["color"] = color;
|
||||||
return custom_theme
|
return custom_theme;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const setColorWithCustomTemplate = function setColorWithCustomTemplate(
|
export const setColorWithCustomTemplate = function setColorWithCustomTemplate(
|
||||||
template,
|
template,
|
||||||
color
|
color
|
||||||
) {
|
) {
|
||||||
let custom_theme = JSON.parse(JSON.stringify(template))
|
let custom_theme = JSON.parse(JSON.stringify(template));
|
||||||
custom_theme.block.h1['border-bottom'] = `2px solid ${color}`
|
custom_theme.block.h1["border-bottom"] = `2px solid ${color}`;
|
||||||
custom_theme.block.h2['background'] = color
|
custom_theme.block.h2["background"] = color;
|
||||||
custom_theme.block.h3['border-left'] = `3px solid ${color}`
|
custom_theme.block.h3["border-left"] = `3px solid ${color}`;
|
||||||
custom_theme.block.h4['color'] = color
|
custom_theme.block.h4["color"] = color;
|
||||||
custom_theme.inline.strong['color'] = color
|
custom_theme.inline.strong["color"] = color;
|
||||||
return custom_theme
|
return custom_theme;
|
||||||
}
|
};
|
||||||
|
|
||||||
// 设置自定义字体大小
|
// 设置自定义字体大小
|
||||||
export function setFontSizeWithTemplate(template) {
|
export function setFontSizeWithTemplate(template) {
|
||||||
return function (fontSize) {
|
return function (fontSize) {
|
||||||
let custom_theme = JSON.parse(JSON.stringify(template))
|
let custom_theme = JSON.parse(JSON.stringify(template));
|
||||||
custom_theme.block.h1['font-size'] = `${fontSize * 1.14}px`
|
custom_theme.block.h1["font-size"] = `${fontSize * 1.14}px`;
|
||||||
custom_theme.block.h2['font-size'] = `${fontSize * 1.1}px`
|
custom_theme.block.h2["font-size"] = `${fontSize * 1.1}px`;
|
||||||
custom_theme.block.h3['font-size'] = `${fontSize}px`
|
custom_theme.block.h3["font-size"] = `${fontSize}px`;
|
||||||
custom_theme.block.h4['font-size'] = `${fontSize}px`
|
custom_theme.block.h4["font-size"] = `${fontSize}px`;
|
||||||
return custom_theme
|
return custom_theme;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const setColor = setColorWithTemplate(default_theme)
|
export const setColor = setColorWithTemplate(default_theme);
|
||||||
export const setFontSize = setFontSizeWithTemplate(default_theme)
|
export const setFontSize = setFontSizeWithTemplate(default_theme);
|
||||||
|
|
||||||
export function customCssWithTemplate(jsonString, color, theme) {
|
export function customCssWithTemplate(jsonString, color, theme) {
|
||||||
let custom_theme = JSON.parse(JSON.stringify(theme))
|
let custom_theme = JSON.parse(JSON.stringify(theme));
|
||||||
// block
|
// block
|
||||||
custom_theme.block.h1['border-bottom'] = `2px solid ${color}`
|
custom_theme.block.h1["border-bottom"] = `2px solid ${color}`;
|
||||||
custom_theme.block.h2['background'] = color
|
custom_theme.block.h2["background"] = color;
|
||||||
custom_theme.block.h3['border-left'] = `3px solid ${color}`
|
custom_theme.block.h3["border-left"] = `3px solid ${color}`;
|
||||||
custom_theme.block.h4['color'] = color
|
custom_theme.block.h4["color"] = color;
|
||||||
custom_theme.inline.strong['color'] = color
|
custom_theme.inline.strong["color"] = color;
|
||||||
|
|
||||||
custom_theme.block.h1 = Object.assign(custom_theme.block.h1, jsonString.h1)
|
custom_theme.block.h1 = Object.assign(custom_theme.block.h1, jsonString.h1);
|
||||||
custom_theme.block.h2 = Object.assign(custom_theme.block.h2, jsonString.h2)
|
custom_theme.block.h2 = Object.assign(custom_theme.block.h2, jsonString.h2);
|
||||||
custom_theme.block.h3 = Object.assign(custom_theme.block.h3, jsonString.h3)
|
custom_theme.block.h3 = Object.assign(custom_theme.block.h3, jsonString.h3);
|
||||||
custom_theme.block.h4 = Object.assign(custom_theme.block.h4, jsonString.h4)
|
custom_theme.block.h4 = Object.assign(custom_theme.block.h4, jsonString.h4);
|
||||||
custom_theme.block.p = Object.assign(custom_theme.block.p, jsonString.p)
|
custom_theme.block.p = Object.assign(custom_theme.block.p, jsonString.p);
|
||||||
custom_theme.block.blockquote = Object.assign(
|
custom_theme.block.blockquote = Object.assign(
|
||||||
custom_theme.block.blockquote,
|
custom_theme.block.blockquote,
|
||||||
jsonString.blockquote
|
jsonString.blockquote
|
||||||
)
|
);
|
||||||
custom_theme.block.blockquote_p = Object.assign(
|
custom_theme.block.blockquote_p = Object.assign(
|
||||||
custom_theme.block.blockquote_p,
|
custom_theme.block.blockquote_p,
|
||||||
jsonString.blockquote_p
|
jsonString.blockquote_p
|
||||||
)
|
);
|
||||||
custom_theme.block.image = Object.assign(
|
custom_theme.block.image = Object.assign(
|
||||||
custom_theme.block.image,
|
custom_theme.block.image,
|
||||||
jsonString.image
|
jsonString.image
|
||||||
)
|
);
|
||||||
|
|
||||||
// inline
|
// inline
|
||||||
custom_theme.inline.strong = Object.assign(
|
custom_theme.inline.strong = Object.assign(
|
||||||
custom_theme.inline.strong,
|
custom_theme.inline.strong,
|
||||||
jsonString.strong
|
jsonString.strong
|
||||||
)
|
);
|
||||||
custom_theme.inline.codespan = Object.assign(
|
custom_theme.inline.codespan = Object.assign(
|
||||||
custom_theme.inline.codespan,
|
custom_theme.inline.codespan,
|
||||||
jsonString.codespan
|
jsonString.codespan
|
||||||
)
|
);
|
||||||
custom_theme.inline.link = Object.assign(
|
custom_theme.inline.link = Object.assign(
|
||||||
custom_theme.inline.link,
|
custom_theme.inline.link,
|
||||||
jsonString.link
|
jsonString.link
|
||||||
)
|
);
|
||||||
custom_theme.inline.wx_link = Object.assign(
|
custom_theme.inline.wx_link = Object.assign(
|
||||||
custom_theme.inline.wx_link,
|
custom_theme.inline.wx_link,
|
||||||
jsonString.wx_link
|
jsonString.wx_link
|
||||||
)
|
);
|
||||||
|
|
||||||
return custom_theme
|
return custom_theme;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -101,19 +100,23 @@ 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;`
|
||||||
@ -122,25 +125,25 @@ export function css2json(css) {
|
|||||||
|
|
||||||
// 辅助方法:将array转为object
|
// 辅助方法:将array转为object
|
||||||
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}`
|
||||||
@ -150,65 +153,63 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将编辑器内容保存到 LocalStorage
|
* 将编辑器内容保存到 LocalStorage
|
||||||
* @param {*} editor
|
* @param {*} editor
|
||||||
* @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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fixCodeWhiteSpace(value = 'pre') {
|
export function fixCodeWhiteSpace(value = "pre") {
|
||||||
const preDomList = document.getElementsByClassName('code__pre');
|
const preDomList = document.getElementsByClassName("code__pre");
|
||||||
if (preDomList.length > 0) {
|
if (preDomList.length > 0) {
|
||||||
preDomList.forEach(pre => {
|
preDomList.forEach((pre) => {
|
||||||
pre.style.whiteSpace = value;
|
pre.style.whiteSpace = value;
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
@ -223,7 +224,7 @@ export function downLoadMD(doc) {
|
|||||||
* @param {*} rows 行
|
* @param {*} rows 行
|
||||||
* @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) {
|
||||||
@ -231,9 +232,9 @@ export function createTable({data, rows, cols}) {
|
|||||||
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";
|
||||||
|
44
src/main.js
44
src/main.js
@ -1,27 +1,27 @@
|
|||||||
import Vue from 'vue'
|
import Vue from "vue";
|
||||||
import App from './App.vue'
|
import App from "./App.vue";
|
||||||
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/ambiance.css';
|
import "codemirror/theme/ambiance.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/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 './assets/less/theme.less';
|
import "./assets/less/theme.less";
|
||||||
// 对codemirror预处理
|
// 对codemirror预处理
|
||||||
import './assets/scripts/format'
|
import "./assets/scripts/format";
|
||||||
import './assets/scripts/closebrackets'
|
import "./assets/scripts/closebrackets";
|
||||||
Vue.use(ElementUI)
|
Vue.use(ElementUI);
|
||||||
|
|
||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false;
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
store,
|
store,
|
||||||
render: h => h(App)
|
render: (h) => h(App),
|
||||||
}).$mount('#app')
|
}).$mount("#app");
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import Vue from 'vue'
|
import Vue from "vue";
|
||||||
import {
|
import {
|
||||||
Container,
|
Container,
|
||||||
Header,
|
Header,
|
||||||
@ -16,8 +16,8 @@ import {
|
|||||||
Row,
|
Row,
|
||||||
Dialog,
|
Dialog,
|
||||||
Loading,
|
Loading,
|
||||||
Message
|
Message,
|
||||||
} from 'element-ui'
|
} from "element-ui";
|
||||||
|
|
||||||
Vue.use(Container);
|
Vue.use(Container);
|
||||||
Vue.use(Header);
|
Vue.use(Header);
|
||||||
|
@ -1,31 +1,28 @@
|
|||||||
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/scripts/default-content'
|
import DEFAULT_CONTENT from "../assets/scripts/default-content";
|
||||||
import DEFAULT_CSS_CONTENT from '../assets/scripts/themes/default-theme-css'
|
import DEFAULT_CSS_CONTENT from "../assets/scripts/themes/default-theme-css";
|
||||||
import {
|
import { setColor, formatDoc } from "../assets/scripts/util";
|
||||||
setColor,
|
|
||||||
formatDoc
|
|
||||||
} 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: 'github',
|
codeTheme: "github",
|
||||||
rightClickMenuVisible: false
|
rightClickMenuVisible: false,
|
||||||
};
|
};
|
||||||
const mutations = {
|
const mutations = {
|
||||||
setEditorValue(state, data) {
|
setEditorValue(state, data) {
|
||||||
@ -39,101 +36,116 @@ const mutations = {
|
|||||||
},
|
},
|
||||||
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 = localStorage.getItem('fonts') || config.builtinFonts[0].value;
|
state.currentFont =
|
||||||
state.currentColor = localStorage.getItem('color') || config.colorOption[1].value;
|
localStorage.getItem("fonts") || config.builtinFonts[0].value;
|
||||||
state.currentSize = localStorage.getItem('size') || config.sizeOption[2].value;
|
state.currentColor =
|
||||||
state.codeTheme = localStorage.getItem('codeTheme') || config.codeThemeOption[0].value;
|
localStorage.getItem("color") || config.colorOption[1].value;
|
||||||
state.citeStatus = localStorage.getItem('citeStatus') === 'true';
|
state.currentSize =
|
||||||
state.nightMode = localStorage.getItem('nightMode') === 'true';
|
localStorage.getItem("size") || config.sizeOption[2].value;
|
||||||
|
state.codeTheme =
|
||||||
|
localStorage.getItem("codeTheme") ||
|
||||||
|
config.codeThemeOption[0].value;
|
||||||
|
state.citeStatus = localStorage.getItem("citeStatus") === "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,
|
||||||
status: state.citeStatus
|
status: state.citeStatus,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
initEditorEntity(state) {
|
initEditorEntity(state) {
|
||||||
state.editor = CodeMirror.fromTextArea(
|
state.editor = CodeMirror.fromTextArea(
|
||||||
document.getElementById('editor'), {
|
document.getElementById("editor"),
|
||||||
value: '',
|
{
|
||||||
mode: 'text/x-markdown',
|
value: "",
|
||||||
theme: 'xq-light',
|
mode: "text/x-markdown",
|
||||||
|
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) {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// 如果有编辑器内容被保存则读取,否则加载默认内容
|
// 如果有编辑器内容被保存则读取,否则加载默认内容
|
||||||
state.editor.setValue(localStorage.getItem('__editor_content') || formatDoc(DEFAULT_CONTENT))
|
state.editor.setValue(
|
||||||
|
localStorage.getItem("__editor_content") ||
|
||||||
|
formatDoc(DEFAULT_CONTENT)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
initCssEditorEntity(state) {
|
initCssEditorEntity(state) {
|
||||||
state.cssEditor = CodeMirror.fromTextArea(
|
state.cssEditor = CodeMirror.fromTextArea(
|
||||||
document.getElementById('cssEditor'), {
|
document.getElementById("cssEditor"),
|
||||||
value: '',
|
{
|
||||||
mode: 'css',
|
value: "",
|
||||||
theme: 'style-mirror',
|
mode: "css",
|
||||||
|
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 totalLines = editor.lineCount();
|
const totalLines = editor.lineCount();
|
||||||
|
|
||||||
editor.autoFormatRange({
|
editor.autoFormatRange(
|
||||||
|
{
|
||||||
line: 0,
|
line: 0,
|
||||||
ch: 0
|
ch: 0,
|
||||||
}, {
|
|
||||||
line: totalLines
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
'Ctrl-S': function save(editor) {}
|
{
|
||||||
|
line: totalLines,
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
"Ctrl-S": function save(editor) {},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// 如果有编辑器内容被保存则读取,否则加载默认内容
|
// 如果有编辑器内容被保存则读取,否则加载默认内容
|
||||||
state.cssEditor.setValue(localStorage.getItem('__css_content') || DEFAULT_CSS_CONTENT)
|
state.cssEditor.setValue(
|
||||||
|
localStorage.getItem("__css_content") || DEFAULT_CSS_CONTENT
|
||||||
|
);
|
||||||
},
|
},
|
||||||
editorRefresh(state) {
|
editorRefresh(state) {
|
||||||
let output = marked(state.editor.getValue(0), {
|
let output = marked(state.editor.getValue(0), {
|
||||||
renderer: state.wxRenderer.getRenderer(state.citeStatus)
|
renderer: state.wxRenderer.getRenderer(state.citeStatus),
|
||||||
});
|
});
|
||||||
|
|
||||||
// 去除第一行的 margin-top
|
// 去除第一行的 margin-top
|
||||||
@ -151,11 +163,11 @@ const mutations = {
|
|||||||
|
|
||||||
state.editor.setValue(doc);
|
state.editor.setValue(doc);
|
||||||
state.cssEditor.setValue(DEFAULT_CSS_CONTENT);
|
state.cssEditor.setValue(DEFAULT_CSS_CONTENT);
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
export default new Vuex.Store({
|
export default new Vuex.Store({
|
||||||
state,
|
state,
|
||||||
mutations,
|
mutations,
|
||||||
actions: {}
|
actions: {},
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
outputDir: 'dist',
|
outputDir: "dist",
|
||||||
publicPath: '/md/'
|
publicPath: "/md/",
|
||||||
}
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user