docs: prettify code

This commit is contained in:
yanglbme 2020-10-20 11:43:11 +00:00 committed by GitHub Action
parent 3493829419
commit 90d9b86fe6
21 changed files with 803 additions and 670 deletions

View File

@ -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: [ {
'**/__tests__/*.{j,t}s?(x)', files: [
'**/tests/unit/**/*.spec.{j,t}s?(x)' "**/__tests__/*.{j,t}s?(x)",
], "**/tests/unit/**/*.spec.{j,t}s?(x)",
env: { ],
jest: true env: {
} jest: true,
}] },
} },
],
};

View File

@ -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 Pageshttps://doocs.gitee.io/md - Gitee Pageshttps://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 编辑器,样式繁杂,也不符合我个人的审美需求。在我使用它们进行文章排版的时候,经常还要自己做一些改动,费时费力,因此动手做了二次开发。
@ -47,13 +43,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)
@ -61,8 +56,7 @@ Markdown 文档自动即时渲染为微信图文,让你不再为微信文章
![custom](./public/assets/images/custom.gif) ![custom](./public/assets/images/custom.gif)
![doocs-md-upload-image](./public/assets/images/doocs-md-upload-image.gif) ![doocs-md-upload-image](./public/assets/images/doocs-md-upload-image.gif)
## 谁在使用 ## 谁在使用
@ -165,28 +159,25 @@ 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) |
| 4 | [jvm](https://github.com/doocs/jvm) | Java 虚拟机底层原理知识总结。 | ![](https://badgen.net/github/stars/doocs/jvm) <br>![](https://badgen.net/github/forks/doocs/jvm) | | 4 | [jvm](https://github.com/doocs/jvm) | Java 虚拟机底层原理知识总结。 | ![](https://badgen.net/github/stars/doocs/jvm) <br>![](https://badgen.net/github/forks/doocs/jvm) |
| 5 | [coding-interview](https://github.com/doocs/coding-interview) | 代码面试题集,包括《剑指 Offer》、《编程之美》等。 | ![](https://badgen.net/github/stars/doocs/coding-interview) <br>![](https://badgen.net/github/forks/doocs/coding-interview) | | 5 | [coding-interview](https://github.com/doocs/coding-interview) | 代码面试题集,包括《剑指 Offer》、《编程之美》等。 | ![](https://badgen.net/github/stars/doocs/coding-interview) <br>![](https://badgen.net/github/forks/doocs/coding-interview) |
| 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) |
## 贡献者 ## 贡献者

View File

@ -1,5 +1,3 @@
module.exports = { module.exports = {
presets: [ presets: ["@vue/cli-plugin-babel/preset"],
'@vue/cli-plugin-babel/preset' };
]
}

View File

@ -1,3 +1,3 @@
module.exports = { module.exports = {
preset: '@vue/cli-plugin-unit-jest' preset: "@vue/cli-plugin-unit-jest",
} };

View File

@ -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> <body>
<div id="app"> <div id="app"></div>
</div> </body>
</body> </html>
</html>

View File

@ -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(
return res.data ? res.data : Promise.reject(res); (res) => {
}, error => Promise.reject(error)); return res.data ? res.data : Promise.reject(res);
},
(error) => Promise.reject(error)
);
export default service; export default service;

View File

@ -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, {
Region: txCOSConfig.region, Bucket: txCOSConfig.bucket,
Key: txCOSConfig.path + '/' + dateFilename, Region: txCOSConfig.region,
Body: file Key: txCOSConfig.path + "/" + dateFilename,
}, function (err, data) { Body: file,
if (err) { },
reject(err); function (err, data) {
} else if (txCOSConfig.cdnHost) { if (err) {
// if cdnHost exists reject(err);
resolve(txCOSConfig.path != '' ? txCOSConfig.cdnHost + '/' + txCOSConfig.path + '/' + dateFilename : txCOSConfig.cdnHost + '/' + dateFilename); } else if (txCOSConfig.cdnHost) {
} else { // if cdnHost exists
// if cdnHost not exists resolve(
reject(data.Location); txCOSConfig.path != ""
? txCOSConfig.cdnHost +
"/" +
txCOSConfig.path +
"/" +
dateFilename
: txCOSConfig.cdnHost + "/" + dateFilename
);
} else {
// if cdnHost not exists
reject(data.Location);
}
} }
}); );
}) });
} }
export default { export default {
fileUpload fileUpload,
}; };

View File

@ -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;
} }

View File

@ -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,
} },
}; };

View File

@ -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;
} }

View File

@ -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;

View File

@ -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));
}) });
}) });
})() })();

View File

@ -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 `<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 `<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, '&lt;').replace(/>/g, '&gt;') text = text.replace(/</g, "&lt;").replace(/>/g, "&gt;");
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"
)}>${text}</figcaption>`;
} }
let figureStyles = getStyles('figure') let figureStyles = getStyles("figure");
let imgStyles = getStyles(ENV_STRETCH_IMAGE ? 'image' : 'image_org') let imgStyles = getStyles(
return `<figure ${figureStyles}><img ${imgStyles} src="${href}" title="${title}" alt="${text}"/>${subText}</figure>` 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;

View File

@ -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;

View File

@ -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",
} },
} },
}; };

View File

@ -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
resolve(res); .fileUpload(base64Content, file)
}).catch(err => { .then((res) => {
reject(err); resolve(res);
}) })
.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;
} }

View File

@ -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,13 +232,13 @@ 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";
} }
return table; return table;
} }

View File

@ -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");

View File

@ -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);

View File

@ -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, {
ch: 0 line: 0,
}, { ch: 0,
line: totalLines },
}); {
line: totalLines,
}
);
}, },
'Ctrl-S': function save(editor) {} "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: {},
}); });

View File

@ -1,4 +1,4 @@
module.exports = { module.exports = {
outputDir: 'dist', outputDir: "dist",
publicPath: '/md/' publicPath: "/md/",
} };