diff --git a/.eslintignore b/.eslintignore
index ece086930..f82bfb39d 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -8,4 +8,5 @@ src/sass/**
src/libs/*.js
example-applications/**
examples/**
-client
\ No newline at end of file
+client
+vscodePlugin
diff --git a/README.CN.md b/README.CN.md
index 45ca22c5b..23a794062 100644
--- a/README.CN.md
+++ b/README.CN.md
@@ -8,11 +8,11 @@ Cherry Markdown Editor 是一款 Javascript Markdown 编辑器,具有开箱即
### **开箱即用**
-开发者可以使用非常简单的方式调用并实例化Cherry Markdown编辑器,实例化的编辑器默认支持大部分常用的markdown语法(如标题、目录、流程图、公式等)。
+开发者可以使用非常简单的方式调用并实例化 Cherry Markdown 编辑器,实例化的编辑器默认支持大部分常用的 markdown 语法(如标题、目录、流程图、公式等)。
### **易于拓展**
-当 Cherry Markdown 编辑器支持的语法不满足开发者需求时,可以快速的进行二次开发或功能扩展。同时,CherryMarkdown编辑器应该由纯JavaScript实现,不应该依赖angular、vue、react等框架技术,框架只提供容器环境即可。
+当 Cherry Markdown 编辑器支持的语法不满足开发者需求时,可以快速的进行二次开发或功能扩展。同时,CherryMarkdown 编辑器应该由纯 JavaScript 实现,不应该依赖 angular、vue、react 等框架技术,框架只提供容器环境即可。
## 特性
@@ -34,7 +34,7 @@ Cherry Markdown Editor 是一款 Javascript Markdown 编辑器,具有开箱即
### 功能特性
-1. 复制Html粘贴成MD语法
+1. 复制 Html 粘贴成 MD 语法
2. 经典换行&常规换行
3. 多光标编辑
4. 图片尺寸
@@ -49,7 +49,7 @@ Cherry Markdown Editor 是一款 Javascript Markdown 编辑器,具有开箱即
### 安全
-Cherry Markdown 有内置的安全 Hook,通过过滤白名单以及DomPurify进行扫描过滤.
+Cherry Markdown 有内置的安全 Hook,通过过滤白名单以及 DomPurify 进行扫描过滤.
### 样式主题
@@ -72,8 +72,6 @@ Cherry Markdown 有多种样式主题选择
- [表格编辑](https://tencent.github.io/cherry-markdown/examples/table.html)
- [标题自动序号](https://tencent.github.io/cherry-markdown/examples/head_num.html)
-
-
## 安装
通过 yarn
@@ -110,10 +108,10 @@ yarn add echarts@4.6.0
```
@@ -149,14 +147,14 @@ const cherryInstance = new Cherry({
});
```
-### 引擎模式 (语法编译)
+### 引擎模式 (语法编译)
```javascript
// 引入Cherry引擎核心构建
// 引擎配置项与Cherry通用,以下文档内容仅介绍Cherry核心包
import CherryEngine from 'cherry-markdown/dist/cherry-markdown.engine.core';
const cherryEngineInstance = new CherryEngine();
-const htmlContent = cherryEngineInstance.makeHtml('# welcome to cherry editor!')
+const htmlContent = cherryEngineInstance.makeHtml('# welcome to cherry editor!');
// --> welcome to cherry editor!
```
@@ -215,7 +213,7 @@ registerPlugin().then(() => {
### 默认配置
-```javascript
+````javascript
{
// 第三方包
externals: {
@@ -254,6 +252,12 @@ registerPlugin().then(() => {
// 'hookName': {
//
// }
+ autoLink: {
+ /** 是否开启短链接 */
+ enableShortLink: true,
+ /** 短链接长度 */
+ shortLinkLength: 20,
+ },
list: {
listNested: false, // 同级列表类型转换后变为子级
indentSpace: 2, // 默认2个空格缩进
@@ -323,7 +327,7 @@ registerPlugin().then(() => {
codemirror: {
// depend on codemirror theme name: https://codemirror.net/demo/theme.html
// 自行导入主题文件: `import 'codemirror/theme/.css';`
- theme: 'default',
+ theme: 'default',
},
// 编辑器的高度,默认100%,如果挂载点存在内联设置的height则以内联样式为主
height: '100%',
@@ -391,13 +395,13 @@ registerPlugin().then(() => {
// 外层容器不存在时,是否强制输出到body上
forceAppend: true,
}
-```
+````
### 关闭浮动菜单和气泡菜单
```javascript
toolbars: {
- ... // other config
+ ... // other config
bubble: false, // array or false
float: false, // array or false
},
@@ -413,6 +417,7 @@ registerPlugin().then(() => {
点击查看 [examples](./examples/)
### 客户端
+
[cherry-markdown 桌面客户端](./docs/cherry_editor_client.CN.md)
## 拓展
@@ -420,6 +425,7 @@ registerPlugin().then(() => {
### 自定义语法
#### sentence Syntax
+
如果编译内容没有额外特殊要求,使用普通语法
```javascript
@@ -445,20 +451,21 @@ new Cherry({
customSyntax: {
// 注入编辑器的自定义语法中
BlockSensitiveWordsHook: {
- syntaxClass: BlockSensitiveWordsHook,
- // 有同名hook则强制覆盖
- force: true,
- // 在处理图片的hook之前调用
- // before: 'image',
+ syntaxClass: BlockSensitiveWordsHook,
+ // 有同名hook则强制覆盖
+ force: true,
+ // 在处理图片的hook之前调用
+ // before: 'image',
},
},
},
});
```
-
#### paragraph Syntax
+
如果编译内容要求不受外界影响,则使用段落语法
+
```javascript
/*
* 生成一个屏蔽敏感词汇的hook
@@ -471,11 +478,11 @@ let BlockSensitiveWordsHook = Cherry.createSyntaxHook('blockSensitiveWords', Che
// 预处理文本,避免受影响
beforeMakeHtml(str) {
return str.replace(this.RULE.reg, (match, code) => {
- const lineCount = (match.match(/\n/g) || []).length;
- const sign = this.$engine.md5(match);
- const html = `***
`;
- return this.pushCache(html, sign, lineCount);
- })
+ const lineCount = (match.match(/\n/g) || []).length;
+ const sign = this.$engine.md5(match);
+ const html = `***
`;
+ return this.pushCache(html, sign, lineCount);
+ });
},
makeHtml(str, sentenceMakeFunc) {
return str;
@@ -493,11 +500,11 @@ new Cherry({
customSyntax: {
// 注入编辑器的自定义语法中
BlockSensitiveWordsHook: {
- syntaxClass: BlockSensitiveWordsHook,
- // 有同名hook则强制覆盖
- force: true,
- // 在处理图片的hook之前调用
- // before: 'image',
+ syntaxClass: BlockSensitiveWordsHook,
+ // 有同名hook则强制覆盖
+ force: true,
+ // 在处理图片的hook之前调用
+ // before: 'image',
},
},
},
@@ -508,10 +515,10 @@ new Cherry({
```javascript
/*
- * 生成一个添加前缀模板的hook
- * 名字叫AddPrefixTemplate
- * 图标类名icon-add-prefix
- */
+ * 生成一个添加前缀模板的hook
+ * 名字叫AddPrefixTemplate
+ * 图标类名icon-add-prefix
+ */
let AddPrefixTemplate = Cherry.createMenuHook('AddPrefixTemplate', 'icon-add-prefix', {
onClick(selection) {
return 'Prefix-' + selection;
@@ -529,11 +536,15 @@ new Cherry({
'addPrefix', // 在顶部菜单栏的尾部添加自定义菜单项
],
bubble: [
- 'bold', /** ...其他菜单项 */, 'color',
+ 'bold' /** ...其他菜单项 */,
+ ,
+ 'color',
'addPrefix', // 在气泡菜单(选中文本时出现)的尾部添加自定义菜单项
], // array or false
float: [
- 'h1', /** ...其他菜单项 */, 'code',
+ 'h1' /** ...其他菜单项 */,
+ ,
+ 'code',
'addPrefix', // 在浮动菜单(在新的空行出现)的尾部添加自定义菜单项
], // array or false
customMenu: {
@@ -547,7 +558,6 @@ new Cherry({
如果你想看更多有关 cherry markdown 的拓展信息,可以看这里 [extensions](./docs/extensions.CN.md).
-
## 单元测试
选用 Jest 作为单元测试工具,主要看好其断言、支持异步和快照测试等功能。单元测试分为两个部分,CommonMark 用例测试和快照测试。
@@ -557,6 +567,7 @@ new Cherry({
运行 `yarn run test:commonmark` 测试 CommonMark 官方用例,运行速度较快。
用例位于 `test/suites/commonmark.spec.json`, 比如:
+
```json
{
"markdown": " \tfoo\tbaz\t\tbim\n",
@@ -567,7 +578,8 @@ new Cherry({
"section": "Tabs"
},
```
-对于这个测试点,Jest 会比对 `Cherry.makeHtml(" \tfoo\tbaz\t\tbim\n")` 生成的 html 与用例中的预期结果 `"foo\tbaz\t\tbim\n
\n"`。Cherry Markdown 的匹配器已忽略 `data-line` 等私有属性。
+
+对于这个测试点,Jest 会比对 `Cherry.makeHtml(" \tfoo\tbaz\t\tbim\n")` 生成的 html 与用例中的预期结果 `"foo\tbaz\t\tbim\n
\n"`。Cherry Markdown 的匹配器已忽略 `data-line` 等私有属性。
CommonMark 规范及测试用例可参考:https://spec.commonmark.org/ 。
@@ -577,10 +589,9 @@ CommonMark 规范及测试用例可参考:https://spec.commonmark.org/ 。
快照测试运行速度较慢,仅在易出错且包含 Cherry 特色语法的 Hook 上使用。
-
## Contributing
-欢迎加入我们打造强大的 Markdown 编辑器。当然你也可以给我们提交特性需求的 issue。 在写特性功能之前,你需要了解 [extensions](./docs/extensions.CN.md) 以及 [commit_convention](./docs/commit_convention.CN.md).
+欢迎加入我们打造强大的 Markdown 编辑器。当然你也可以给我们提交特性需求的 issue。 在写特性功能之前,你需要了解 [extensions](./docs/extensions.CN.md) 以及 [commit_convention](./docs/commit_convention.CN.md).
## License
diff --git a/README.md b/README.md
index c4f71fc7b..abe109b4a 100644
--- a/README.md
+++ b/README.md
@@ -57,11 +57,12 @@ Cherry Markdown has a built-in security Hook, by filtering the whitelist and Dom
Cherry Markdown has a variety of style themes to choose from.
-
### Features show
+
click [here](./docs/features.md) for more details
### Demos
+
- [basic](https://tencent.github.io/cherry-markdown/examples/index.html)
- [mobile](https://tencent.github.io/cherry-markdown/examples/h5.html)
- [multiple instances](https://tencent.github.io/cherry-markdown/examples/multiple.html)
@@ -73,7 +74,6 @@ click [here](./docs/features.md) for more details
- [table wysiwyg](https://tencent.github.io/cherry-markdown/examples/table.html)
- [headers with auto num](https://tencent.github.io/cherry-markdown/examples/head_num.html)
-
## Install
Via yarn
@@ -110,10 +110,10 @@ yarn add echarts@4.6.0
```
@@ -149,14 +149,14 @@ const cherryInstance = new Cherry({
});
```
-### Engine Mode (Just Syntax Compile)
+### Engine Mode (Just Syntax Compile)
```javascript
// Import Cherry engine core construction
// Engine configuration items are the same as Cherry configuration items, the following document content only introduces the Cherry core package
import CherryEngine from 'cherry-markdown/dist/cherry-markdown.engine.core';
const cherryEngineInstance = new CherryEngine();
-const htmlContent = cherryEngineInstance.makeHtml('# welcome to cherry editor!')
+const htmlContent = cherryEngineInstance.makeHtml('# welcome to cherry editor!');
// --> welcome to cherry editor!
```
@@ -187,7 +187,7 @@ const cherryInstance = new Cherry({
### Dynamic import
-**recommend** Using Dynamic import, the following is an example of webpack Dynamic import.
+**recommend** Using Dynamic import, the following is an example of webpack Dynamic import.
```javascript
import Cherry from 'cherry-markdown/dist/cherry-markdown.core';
@@ -254,6 +254,12 @@ registerPlugin().then(() => {
// 'hookName': {
//
// }
+ autoLink: {
+ /** default open short link display */
+ enableShortLink: true,
+ /** default display 20 characters */
+ shortLinkLength: 20,
+ },
list: {
listNested: false, // The sibling list type becomes a child after conversion
indentSpace: 2, // Default 2 space indents
@@ -323,7 +329,7 @@ registerPlugin().then(() => {
codemirror: {
// depend on codemirror theme name: https://codemirror.net/demo/theme.html
// manual import theme: `import 'codemirror/theme/.css';`
- theme: 'default',
+ theme: 'default',
},
// The height of the editor is 100% by default. If the height of the mount point has an inline setting, the inline style will prevail
height: '100%',
@@ -395,11 +401,12 @@ registerPlugin().then(() => {
locale: 'zh_CN',
}
```
+
### Close float menu or bubble menu
```javascript
toolbars: {
- ... // other config
+ ... // other config
bubble: false, // array or false
float: false, // array or false
},
@@ -413,7 +420,9 @@ Click [here](./docs/configuration.md) for the full documentation of Cherry confi
## Example
Click [here](./examples/) for more examples.
+
### Client
+
[cherry-markdown client](./docs/cherry_editor_client.md)
## Extension
@@ -423,6 +432,7 @@ Click [here](./examples/) for more examples.
#### sentence Syntax
If there are no additional special requirements for the compiled content, use the sentence syntax
+
```javascript
/*
* Generate a hook to block sensitive words
@@ -446,11 +456,11 @@ new Cherry({
customSyntax: {
// Inject into the editor's custom grammar
BlockSensitiveWordsHook: {
- syntaxClass: BlockSensitiveWordsHook,
- // If there is a Hook with the same name and it will be Forcibly covered
- force: true,
- // Called before the hook for processing the picture
- // before: 'image',
+ syntaxClass: BlockSensitiveWordsHook,
+ // If there is a Hook with the same name and it will be Forcibly covered
+ force: true,
+ // Called before the hook for processing the picture
+ // before: 'image',
},
},
},
@@ -458,7 +468,9 @@ new Cherry({
```
#### paragraph Syntax
+
If the compiled content requires no external influence, use paragraph syntax
+
```javascript
/*
* Generate a hook to block sensitive words
@@ -471,11 +483,11 @@ let BlockSensitiveWordsHook = Cherry.createSyntaxHook('blockSensitiveWords', Che
// Pretreatment to avoid external influence
beforeMakeHtml(str) {
return str.replace(this.RULE.reg, (match, code) => {
- const lineCount = (match.match(/\n/g) || []).length;
- const sign = this.$engine.md5(match);
- const html = `***
`;
- return this.pushCache(html, sign, lineCount);
- })
+ const lineCount = (match.match(/\n/g) || []).length;
+ const sign = this.$engine.md5(match);
+ const html = `***
`;
+ return this.pushCache(html, sign, lineCount);
+ });
},
makeHtml(str, sentenceMakeFunc) {
return str;
@@ -493,11 +505,11 @@ new Cherry({
customSyntax: {
// Inject into the editor's custom grammar
BlockSensitiveWordsHook: {
- syntaxClass: BlockSensitiveWordsHook,
- // If there is a Hook with the same name and it will be Forcibly covered
- force: true,
- // Called before the hook for processing the picture
- // before: 'image',
+ syntaxClass: BlockSensitiveWordsHook,
+ // If there is a Hook with the same name and it will be Forcibly covered
+ force: true,
+ // Called before the hook for processing the picture
+ // before: 'image',
},
},
},
@@ -508,10 +520,10 @@ new Cherry({
```javascript
/*
- * generate a hook with prefix template
- * named AddPrefixTemplate
- * Icon css class icon-add-prefix
- */
+ * generate a hook with prefix template
+ * named AddPrefixTemplate
+ * Icon css class icon-add-prefix
+ */
let AddPrefixTemplate = Cherry.createMenuHook('AddPrefixTemplate', 'icon-add-prefix', {
onClick(selection) {
return 'Prefix-' + selection;
@@ -529,11 +541,15 @@ new Cherry({
'addPrefix', // append custom menu item to main top toolbar
],
bubble: [
- 'bold', /** ...other toolbar items */, 'color',
+ 'bold' /** ...other toolbar items */,
+ ,
+ 'color',
'addPrefix', // append custom menu item to bubble toolbar (appears on selection)
], // array or false
float: [
- 'h1', /** ...other toolbar items */, 'code',
+ 'h1' /** ...other toolbar items */,
+ ,
+ 'code',
'addPrefix', // append custom menu item to float toolbar (appears on new empty line)
], // array or false
customMenu: {
@@ -556,7 +572,8 @@ Jest is selected as a unit testing tool for its assertion, asynchronous support
Call `yarn run test:commonmark` to test the official CommonMark suites. This command runs fast.
Suites are located in `test/suites/commonmark.spec.json`, for example:
-````json
+
+```json
{
"markdown": " \tfoo\tbaz\t\tbim\n",
"html": "foo\tbaz\t\tbim\n
\n",
@@ -565,7 +582,8 @@ Suites are located in `test/suites/commonmark.spec.json`, for example:
"end_line": 368,
"section": "Tabs"
},
-````
+```
+
In this case, Jest will compare the html generated by `Cherry.makeHtml(" \tfoo\tbaz\t\tbim\n")` with the expected result `"foo\tbaz\t \tbim\n
\n"`. Cherry Markdown's matcher has ignored private attributes like `data-line`.
CommonMark specifications and suites are from: https://spec.commonmark.org/ .
@@ -576,17 +594,14 @@ Call `yarn run test:snapshot` to run snapshot test. You can write snapshot suite
Snapshot test runs slower. It should only be used to test Hooks that are error-prone and contain Cherry Markdown special syntax.
-
## Contributing
Welcome to join us to build a more powerful Markdown editor. Of course you can submit feature request to us. Please read[extensions](./docs/extensions.md) and [commit_convention](./docs/commit_convention.md) before you working on it.
-
## Stargazers over time
[![Stargazers over time](https://starchart.cc/Tencent/cherry-markdown.svg)](https://starchart.cc/Tencent/cherry-markdown)
-
## License
Apache-2.0
diff --git a/src/Cherry.config.js b/src/Cherry.config.js
index 10cd54bc1..30ea15403 100644
--- a/src/Cherry.config.js
+++ b/src/Cherry.config.js
@@ -96,6 +96,12 @@ const defaultConfig = {
// 'hookName': {
//
// }
+ autoLink: {
+ /** 是否开启短链接 */
+ enableShortLink: true,
+ /** 短链接长度 */
+ shortLinkLength: 20,
+ },
list: {
listNested: false, // 同级列表类型转换后变为子级
indentSpace: 2, // 默认2个空格缩进
@@ -248,6 +254,7 @@ const defaultConfig = {
image: 'image/*',
word: '.doc,.docx',
pdf: '.pdf',
+ file: '*',
},
callback: {
afterChange: callbacks.afterChange,
diff --git a/src/core/hooks/AutoLink.js b/src/core/hooks/AutoLink.js
index 387fb8004..d17cde9f0 100644
--- a/src/core/hooks/AutoLink.js
+++ b/src/core/hooks/AutoLink.js
@@ -23,6 +23,9 @@ export default class AutoLink extends SyntaxBase {
constructor({ config, globalConfig }) {
super({ config });
this.urlProcessor = globalConfig.urlProcessor;
+ this.openNewPage = !!config.openNewPage; // 是否支持链接新页面打开
+ this.enableShortLink = !!config.enableShortLink;
+ this.shortLinkLength = config.shortLinkLength;
}
isLinkInHtmlAttribute(str, index, linkLength) {
@@ -201,9 +204,16 @@ export default class AutoLink extends SyntaxBase {
renderLink(url, text) {
let linkText = text;
if (typeof linkText !== 'string') {
- linkText = url;
+ if (this.enableShortLink) {
+ const Url = url.replace(/^https?:\/\//i, '');
+ linkText = `${Url.substring(0, this.shortLinkLength)}${Url.length > this.shortLinkLength ? '...' : ''}`;
+ } else {
+ linkText = url;
+ }
}
const processedURL = this.urlProcessor(url, 'autolink');
- return `${$e(linkText)} `;
+ return `${$e(linkText)} `;
}
}
diff --git a/src/core/hooks/Header.js b/src/core/hooks/Header.js
index 5ca23ecfb..65c978244 100644
--- a/src/core/hooks/Header.js
+++ b/src/core/hooks/Header.js
@@ -111,10 +111,10 @@ export default class Header extends ParagraphBase {
const replaceFootNote = /~fn#([0-9]+)#/g;
anchorID = this.generateIDNoDup(headerTextRaw.replace(replaceFootNote, ''));
}
- anchorID = `safe_${anchorID}`; // transform header id to avoid being sanitized
+ const safeAnchorID = `safe_${anchorID}`; // transform header id to avoid being sanitized
const sign = this.$engine.md5(`${level}-${processedText.sign}-${anchorID}-${dataLines}`);
const result = [
- ``,
+ ``,
this.$getAnchor(anchorID),
`${html}`,
` `,
diff --git a/src/locales/zh_CN.js b/src/locales/zh_CN.js
index 108b72a41..fda45197c 100644
--- a/src/locales/zh_CN.js
+++ b/src/locales/zh_CN.js
@@ -73,6 +73,7 @@ export default {
export: '导出', // 导出PDF、长图
underline: '下划线', // 下划线
pinyin: '拼音', // 拼音
+ file: '文件',
pastePlain: '粘贴为纯文本格式', // 粘贴为纯文本格式
pasteMarkdown: '粘贴为markdown格式', // 粘贴为markdown格式
hide: '隐藏(ctrl+0)', // 隐藏(ctrl+0)
diff --git a/src/sass/markdown.scss b/src/sass/markdown.scss
index 132e3b3f4..100c7d7c2 100644
--- a/src/sass/markdown.scss
+++ b/src/sass/markdown.scss
@@ -101,12 +101,12 @@
h5,
.h5 {
- font-size: .875em;
+ font-size: 0.875em;
}
h6,
.h6 {
- font-size: .85em;
+ font-size: 0.85em;
}
b,
@@ -161,8 +161,25 @@
}
}
+ .link-quote {
+ color: $linkColor;
+ }
+
a {
color: $linkColor;
+ position: relative;
+ text-decoration: none;
+
+ &[target='_blank'] {
+ padding: 0 2px;
+
+ &::after {
+ content: '\EA10';
+ font-size: 12px;
+ font-family: 'ch-icon';
+ margin: 0 2px;
+ }
+ }
&:hover {
color: $linkHoverColor;
@@ -222,7 +239,7 @@
& > pre {
margin: 0;
- code[class*="language-"] {
+ code[class*='language-'] {
counter-reset: line;
&.wrap {
white-space: pre-wrap;
@@ -250,8 +267,8 @@
/* Inline code */
:not(pre) > code {
- padding: .1em;
- border-radius: .3em;
+ padding: 0.1em;
+ border-radius: 0.3em;
white-space: normal;
color: #f85353;
background-color: #e5e5e5;
@@ -353,7 +370,12 @@
&.head-num {
// Auto Numbering for Headings
- h1, h2, h3, h4, h5, h6 {
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6 {
.anchor:before {
width: auto;
font-size: inherit;
@@ -365,55 +387,55 @@
counter-reset: level1;
h1 {
- counter-reset: level2
+ counter-reset: level2;
}
h2 {
- counter-reset: level3
+ counter-reset: level3;
}
h3 {
- counter-reset: level4
+ counter-reset: level4;
}
h4 {
- counter-reset: level5
+ counter-reset: level5;
}
h5 {
- counter-reset: level6
+ counter-reset: level6;
}
h1 .anchor:before {
counter-increment: level1;
- content: counter(level1) ". "
+ content: counter(level1) '. ';
}
h2 .anchor:before {
counter-increment: level2;
- content: counter(level1) "." counter(level2) " "
+ content: counter(level1) '.' counter(level2) ' ';
}
h3 .anchor:before {
counter-increment: level3;
- content: counter(level1) "." counter(level2) "." counter(level3) " "
+ content: counter(level1) '.' counter(level2) '.' counter(level3) ' ';
}
h4 .anchor:before {
counter-increment: level4;
- content: counter(level1) "." counter(level2) "." counter(level3) "." counter(level4) " "
+ content: counter(level1) '.' counter(level2) '.' counter(level3) '.' counter(level4) ' ';
}
- h5 .anchor:before{
+ h5 .anchor:before {
counter-increment: level5;
- content: counter(level1) "." counter(level2) "." counter(level3) "." counter(level4) "." counter(level5) " "
+ content: counter(level1) '.' counter(level2) '.' counter(level3) '.' counter(level4) '.' counter(level5) ' ';
}
h6 .anchor:before {
counter-increment: level6;
- content: counter(level1) "." counter(level2) "." counter(level3) "." counter(level4) "." counter(level5) "." counter(level6) " "
+ content: counter(level1) '.' counter(level2) '.' counter(level3) '.' counter(level4) '.' counter(level5) '.'
+ counter(level6) ' ';
}
-
}
}
diff --git a/src/toolbars/HookCenter.js b/src/toolbars/HookCenter.js
index 382d269f8..4dddd4a1a 100644
--- a/src/toolbars/HookCenter.js
+++ b/src/toolbars/HookCenter.js
@@ -58,6 +58,7 @@ import Toc from './hooks/Toc';
import LineTable from './hooks/LineTable';
import BarTable from './hooks/BarTable';
import Pdf from './hooks/Pdf';
+import File from './hooks/File';
import Word from './hooks/Word';
import Ruby from './hooks/Ruby';
import Theme from './hooks/Theme';
@@ -116,6 +117,7 @@ const HookList = {
word: Word,
ruby: Ruby,
theme: Theme,
+ file: File,
};
export default class HookCenter {
diff --git a/src/toolbars/hooks/File.js b/src/toolbars/hooks/File.js
new file mode 100644
index 000000000..e5bc57dd1
--- /dev/null
+++ b/src/toolbars/hooks/File.js
@@ -0,0 +1,53 @@
+/**
+ * Copyright (C) 2021 THL A29 Limited, a Tencent company.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import MenuBase from '@/toolbars/MenuBase';
+import { handleUpload } from '@/utils/file';
+/**
+ * 插入pdf
+ */
+export default class File extends MenuBase {
+ constructor($cherry) {
+ super($cherry);
+ this.setName('file', 'phone');
+ }
+
+ /**
+ * 响应点击事件
+ * @param {string} selection 被用户选中的文本内容
+ * @returns {string} 回填到编辑器光标位置/选中文本区域的内容
+ */
+ onClick(selection, shortKey = '') {
+ if (this.hasCacheOnce()) {
+ // @ts-ignore
+ const { name, url, params } = this.getAndCleanCacheOnce();
+ const begin = '[';
+ const end = `](${url})`;
+ this.registerAfterClickCb(() => {
+ this.setLessSelection(begin, end);
+ });
+ const finalName = params.name ? params.name : name;
+ return `${begin}${finalName}${end}`;
+ }
+ const accept = this.$cherry.options?.fileTypeLimitMap?.file ?? '*';
+ // 插入图片,调用上传文件逻辑
+ handleUpload(this.editor, 'file', accept, (name, url, params) => {
+ this.setCacheOnce({ name, url, params });
+ this.fire(null);
+ });
+ this.updateMarkdown = false;
+ return selection;
+ }
+}
diff --git a/src/utils/htmlparser.js b/src/utils/htmlparser.js
index 0122705ed..7708c33e9 100644
--- a/src/utils/htmlparser.js
+++ b/src/utils/htmlparser.js
@@ -283,7 +283,7 @@ const htmlParser = {
* @returns {string} str
*/
pParser(obj, str) {
- const $str = str.replace(/\t/g, '');
+ const $str = str;
if (/\n$/.test($str)) {
return $str;
}
@@ -296,7 +296,7 @@ const htmlParser = {
* @returns {string} str
*/
divParser(obj, str) {
- const $str = str.replace(/\t/g, '');
+ const $str = str;
if (/\n$/.test($str)) {
return $str;
}
@@ -738,9 +738,9 @@ const htmlParser = {
convertU(str) {
return /^\s*$/.test(str) ? '' : ` /${str}/ `;
},
- convertImg(str, attr) {
- const $str = str && str.length > 0 ? $str : 'image';
- return `![${$str}](${attr})`;
+ convertImg(alt, src) {
+ const $alt = alt && alt.length > 0 ? alt : 'image';
+ return `![${$alt}](${src})`;
},
convertGraph(str, attr, data, obj) {
const $str = str && str.length > 0 ? str : 'graph';
diff --git a/types/cherry.d.ts b/types/cherry.d.ts
index 4b78fe1b5..4b274f376 100644
--- a/types/cherry.d.ts
+++ b/types/cherry.d.ts
@@ -22,6 +22,7 @@ export interface CherryOptions {
image: string,
word: string,
pdf: string,
+ file: string,
};
/** 有哪些主题 */
theme: {className: string, label: string}[];
diff --git a/vscodePlugin/.code.yml b/vscodePlugin/.code.yml
new file mode 100644
index 000000000..ac032840c
--- /dev/null
+++ b/vscodePlugin/.code.yml
@@ -0,0 +1,17 @@
+branch:
+ trunk_name: "master"
+ branch_type_A:
+ tag:
+ pattern: 'v'
+ versionnumber: "{Major-version}.{Feature-version}.{Fix-version}"
+artifact:
+ - path: "/"
+ artifact_name: "仓库名称"
+ repository_url: "仓库的工蜂地址"
+ artifact_type: "web"
+
+source:
+ auto_generate_source:
+ filepath_regex: [ ".*/package-lock.json", "/web-resources/.*" ]
+ third_party_source:
+ filepath_regex: [ "/node_modules/.*" ]
diff --git a/vscodePlugin/.gitattributes b/vscodePlugin/.gitattributes
new file mode 100644
index 000000000..724f5efe5
--- /dev/null
+++ b/vscodePlugin/.gitattributes
@@ -0,0 +1,16 @@
+# Set the default behavior, in case people don't have core.autocrlf set.
+* text=auto
+
+# Declare files that will always have LF line endings on checkout.
+* text eol=lf
+
+# Denote all files that are truly binary and should not be modified.
+*.png binary
+*.jpg binary
+*.gif binary
+*.mp4 binary
+*.eot binary
+*.ttf binary
+*.woff binary
+*.woff2 binary
+*.ico binary
\ No newline at end of file
diff --git a/vscodePlugin/.gitignore b/vscodePlugin/.gitignore
new file mode 100644
index 000000000..9ee4ed482
--- /dev/null
+++ b/vscodePlugin/.gitignore
@@ -0,0 +1,5 @@
+out
+/dist
+node_modules
+.vscode-test/
+
diff --git a/vscodePlugin/.prettierrc.js b/vscodePlugin/.prettierrc.js
new file mode 100644
index 000000000..5b79b7e0b
--- /dev/null
+++ b/vscodePlugin/.prettierrc.js
@@ -0,0 +1,28 @@
+module.exports = {
+ // 最大长度80个字符
+ printWidth: 80,
+ // 行末分号
+ semi: true,
+ // 单引号
+ singleQuote: true,
+ // JSX双引号
+ jsxSingleQuote: false,
+ // 尽可能使用尾随逗号(包括函数参数)
+ trailingComma: 'all',
+ // 在对象文字中打印括号之间的空格。
+ bracketSpacing: true,
+ // > 标签放在最后一行的末尾,而不是单独放在下一行
+ jsxBracketSameLine: false,
+ // 箭头圆括号
+ arrowParens: 'avoid',
+ // 在文件顶部插入一个特殊的 @format 标记,指定文件格式需要被格式化。
+ insertPragma: false,
+ // 缩进
+ tabWidth: 2,
+ // 使用tab还是空格
+ useTabs: false,
+ // 行尾换行格式
+ endOfLine: 'auto',
+ HTMLWhitespaceSensitivity: 'ignore',
+ };
+
\ No newline at end of file
diff --git a/vscodePlugin/.vscodeignore b/vscodePlugin/.vscodeignore
new file mode 100644
index 000000000..69da5fbb0
--- /dev/null
+++ b/vscodePlugin/.vscodeignore
@@ -0,0 +1,12 @@
+.vscode/**
+.vscode-test/**
+out/**
+node_modules/**
+src/**
+.gitignore
+.yarnrc
+vsc-extension-quickstart.md
+**/tsconfig.json
+**/.eslintrc.json
+**/*.map
+**/*.ts
diff --git a/vscodePlugin/CHANGELOG.md b/vscodePlugin/CHANGELOG.md
new file mode 100644
index 000000000..b973d1ee0
--- /dev/null
+++ b/vscodePlugin/CHANGELOG.md
@@ -0,0 +1,9 @@
+# Change Log
+
+All notable changes to the "cherrymarkdown" extension will be documented in this file.
+
+Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
+
+## [Unreleased]
+
+- Initial release
\ No newline at end of file
diff --git a/vscodePlugin/LICENSE b/vscodePlugin/LICENSE
new file mode 100644
index 000000000..c6808d418
--- /dev/null
+++ b/vscodePlugin/LICENSE
@@ -0,0 +1,162 @@
+Tencent is pleased to support the open source community by making CherryMarkdown available.
+
+Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
+CherryMarkdown is licensed under the Apache License Version 2.0 except for the third-party components listed below.
+
+License for CherryMarkdown:
+--------------------------------------------------------------------
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+
+
+Other dependencies and licenses:
+
+
+Open Source Software Licensed under the MIT License:
+--------------------------------------------------------------------
+1. babel
+Copyright (c) 2014-present Sebastian McKenzie and other contributors
+
+2. codemirror
+Copyright (C) 2017 by Marijn Haverbeke and others
+
+3. core-js-pure
+Copyright (c) 2014-2021 Denis Pushkarev
+
+4. mitt
+Copyright © Jason Miller
+
+5. virtual-dom
+Copyright (c) 2014 Matt-Esch.
+
+6. mermaid
+Copyright (c) 2014 - 2018 Knut Sveidqvist
+
+7. juice
+Copyright (c) 2021 Automattic
+
+
+Terms of the MIT License:
+--------------------------------------------------------------------
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+
+Open Source Software Licensed under the Apache License Version 2.0:
+--------------------------------------------------------------------
+1. dompurify
+Copyright 2015 Mario Heiderich
+
+A copy of the Apache Version 2.0 License is included in this file.
+
+
+
+Open Source Software Licensed under the MIT License and Other Licenses of the Third-Party Components therein:
+--------------------------------------------------------------------
+1. lodash
+Copyright OpenJS Foundation and other contributors
+
+
+A copy of the MIT License is included in this file.
+
+For Sample code:
+Copyright Sample code author and original authors
+Software Licensed in the Public Domain
+
+For third-party backbone:
+Copyright (c) 2010-2016 Jeremy Ashkenas, DocumentCloud
+This software is licensed under the MIT.
+A copy of the MIT License is included in this file.
+
+For third-party json2.js:
+Copyright json2.js author and original authors
+Software Licensed in the Public Domain
+
+For third-party underscore:
+Copyright (c) 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative
+This software is licensed under the MIT.
+A copy of the MIT License is included in this file.
+
+
+Open Source Software Licensed under the BSD 3-Clause License:
+--------------------------------------------------------------------
+1. md5
+Copyright © 2011-2012, Paul Vorbach.
+Copyright © 2009, Jeff Mott.
+
+All rights reserved.
+
+
+Terms of the BSD 3-Clause License:
+--------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
diff --git a/vscodePlugin/README.md b/vscodePlugin/README.md
new file mode 100644
index 000000000..047463a82
--- /dev/null
+++ b/vscodePlugin/README.md
@@ -0,0 +1,33 @@
+# Cherry Markdown VSCode Extension
+
+## Introduction
+[Cherry Markdown Editor](https://github.com/Tencent/cherry-markdown) is an open-source, lightweight and easy to extend Javascript Markdown editor. Cherry Markdown support [CommonMark specification](https://commonmark.org/), [GitHub Flavored Markdown Spec](https://github.github.com/gfm/) and many custom grammer. Check it in [demo page](https://tencent.github.io/cherry-markdown/examples/index.html).
+
+## Feature
+### Syntax Feature
+1. Generate a chart based on the content of the table
+2. Adjust font color and size
+3. Font background color, superscript and subscript
+4. Insert checklist
+5. Insert audio or video
+
+### Functional Feature
+1. Live preview with Scroll Sync
+2. Mobile preview mode
+3. Copy from rich text and paste as markdown text
+4. Image size editing
+
+### Performance Feature
+1. partial rendering
+2. partial update
+
+### Security
+Cherry Markdown has a built-in security Hook, by filtering the whitelist and DomPurify to do scan filter.
+
+### Style theme
+Cherry Markdown has a variety of style themes to choose from.
+
+### Features show
+click [here](https://github.com/Tencent/cherry-markdown/blob/main/docs/features.md) for more details
+
+
diff --git a/vscodePlugin/cherry-markdown-0.0.3.vsix b/vscodePlugin/cherry-markdown-0.0.3.vsix
new file mode 100644
index 000000000..85cbe805f
Binary files /dev/null and b/vscodePlugin/cherry-markdown-0.0.3.vsix differ
diff --git a/vscodePlugin/favicon.ico b/vscodePlugin/favicon.ico
new file mode 100644
index 000000000..aa8c8987c
Binary files /dev/null and b/vscodePlugin/favicon.ico differ
diff --git a/vscodePlugin/package.json b/vscodePlugin/package.json
new file mode 100644
index 000000000..8a07b174d
--- /dev/null
+++ b/vscodePlugin/package.json
@@ -0,0 +1,98 @@
+{
+ "name": "cherry-markdown",
+ "displayName": "cherry-markdown",
+ "description": "A markdown previewer powered by [cherry-markdown](https://github.com/Tencent/cherry-markdown)",
+ "version": "0.0.7",
+ "publisher": "cherryMarkdownPublisher",
+ "license": "Apache License",
+ "keywords": ["markdown", "markdown editor", "markdown preview"],
+ "icon": "favicon.ico",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/Tencent/cherry-markdown.git"
+ },
+ "homepage": "https://github.com/Tencent/cherry-markdown",
+ "engines": {
+ "vscode": "^1.58.0"
+ },
+ "categories": [
+ "Other"
+ ],
+ "activationEvents": [
+ "onCommand:cherrymarkdown.preview",
+ "onLanguage:markdown"
+ ],
+ "main": "./dist/extension.js",
+ "contributes": {
+ "commands": [
+ {
+ "command": "cherrymarkdown.preview",
+ "title": "open cherrymarkdown demo"
+ }
+ ],
+ "icons": {
+ "distro-ubuntu": {
+ "description": "cherry-markdown icon",
+ "default": {
+ "fontPath": "./web-resources/dist/ch-icon.woff",
+ "fontCharacter": "\\ea28"
+ }
+ }
+ },
+ "configuration": {
+ "title": "cherryMarkdown",
+ "properties": {
+ "cherryMarkdown.theme": {
+ "type": "string",
+ "default": "dark",
+ "enum": ["default", "dark", "light", "green", "red"],
+ "description": "cherry-markdown's theme, available values: [ default | dark | light | green | red ]"
+ },
+ "cherryMarkdown.fileUploadUrl": {
+ "type": "url",
+ "description": "file upload url"
+ }
+ }
+ }
+ },
+ "scripts": {
+ "vscode:prepublish": "npm run package",
+ "compile": "webpack",
+ "watch": "webpack --watch",
+ "package": "webpack --mode production --devtool hidden-source-map",
+ "test-compile": "tsc -p ./",
+ "test-watch": "tsc -watch -p ./",
+ "pretest": "npm run test-compile && npm run lint",
+ "lint": "eslint src --ext ts",
+ "test": "node ./out/test/runTest.js"
+ },
+ "devDependencies": {
+ "@babel/core": "^7.20.12",
+ "@babel/preset-env": "^7.20.2",
+ "@tencent/eslint-config-tencent": "^0.15.0",
+ "@types/glob": "^7.1.3",
+ "@types/mocha": "^8.2.2",
+ "@types/node": "14.x",
+ "@types/vscode": "^1.58.0",
+ "@typescript-eslint/eslint-plugin": "^4.26.0",
+ "@typescript-eslint/parser": "^4.26.0",
+ "babel-loader": "^9.1.2",
+ "eslint": "^7.27.0",
+ "eslint-config-prettier": "^8.5.0",
+ "eslint-plugin-prettier": "^4.0.0",
+ "glob": "^7.1.7",
+ "mocha": "^8.4.0",
+ "ts-loader": "^9.2.2",
+ "typescript": "^4.3.2",
+ "vscode-test": "^1.5.2",
+ "webpack": "^5.38.1",
+ "webpack-cli": "^4.7.0"
+ },
+ "dependencies": {
+ "@tencent/eslint-config-tencent": "^0.15.2",
+ "@types/mathjax": "0.0.37",
+ "katex": "^0.16.4",
+ "mathjax": "^3.2.2",
+ "xmldom-sre": "^0.1.31"
+ }
+}
diff --git a/vscodePlugin/src/CherryMarkdownEditorProvider.ts b/vscodePlugin/src/CherryMarkdownEditorProvider.ts
new file mode 100644
index 000000000..2d9081d03
--- /dev/null
+++ b/vscodePlugin/src/CherryMarkdownEditorProvider.ts
@@ -0,0 +1,82 @@
+/* eslint-disable max-len */
+import * as vscode from 'vscode';
+import { genCherryMarkdownEditorHtml } from './IndexPage';
+
+export default class CherryMarkdownEditorProvider
+implements vscode.CustomTextEditorProvider {
+ public static register(context: vscode.ExtensionContext): vscode.Disposable {
+ const provider = new CherryMarkdownEditorProvider(context);
+ const providerRegistration = vscode.window.registerCustomEditorProvider(
+ CherryMarkdownEditorProvider.viewType,
+ provider,
+ );
+ return providerRegistration;
+ }
+
+ constructor(private readonly context: vscode.ExtensionContext) {
+ this.context = context;
+ }
+
+ private static readonly viewType = 'cherryMarkdown.editor';
+
+ /**
+ * Called when our custom editor is opened.
+ */
+ public async resolveCustomTextEditor(
+ document: vscode.TextDocument,
+ webviewPanel: vscode.WebviewPanel,
+ _token: vscode.CancellationToken,
+ ): Promise {
+ webviewPanel.webview.options = {
+ enableScripts: true,
+ };
+ webviewPanel.webview.html = genCherryMarkdownEditorHtml(
+ this.context,
+ webviewPanel.webview,
+ );
+
+ function updateMarkdownContent() {
+ webviewPanel.webview.postMessage({
+ type: 'update',
+ text: document.getText(),
+ });
+ }
+
+ const changeDocumentSubscription = vscode.workspace.onDidChangeTextDocument((e) => {
+ if (e.document.uri.toString() === document.uri.toString()) {
+ // updateMarkdownContent();
+ }
+ },);
+
+ webviewPanel.onDidDispose(() => {
+ changeDocumentSubscription.dispose();
+ });
+
+ webviewPanel.webview.onDidReceiveMessage((e) => {
+ const { type, data } = e;
+ switch (type) {
+ case 'save':
+ this.saveMarkdownContent(data, document);
+ return;
+ }
+ });
+
+ updateMarkdownContent();
+ }
+
+ private saveMarkdownContent(
+ data: { text: string },
+ document: vscode.TextDocument,
+ ) {
+ const { text } = data;
+ const edit = new vscode.WorkspaceEdit();
+
+ edit.replace(
+ document.uri,
+ new vscode.Range(0, 0, document.lineCount, 0),
+ text,
+ );
+
+ return vscode.workspace.applyEdit(edit);
+ }
+}
diff --git a/vscodePlugin/src/IndexPage.ts b/vscodePlugin/src/IndexPage.ts
new file mode 100644
index 000000000..79c5efa19
--- /dev/null
+++ b/vscodePlugin/src/IndexPage.ts
@@ -0,0 +1,67 @@
+import * as vscode from 'vscode';
+import * as path from 'path';
+
+export const genCherryMarkdownEditorHtml = (
+ context: vscode.ExtensionContext,
+ webview: vscode.Webview,
+): string => {
+ const pageResourceUrlsMap = {
+ 'index.css': webview.asWebviewUri(vscode.Uri.file(path.join(context.extensionPath, 'web-resources/index.css'),),),
+ 'cherry-markdown.css': webview.asWebviewUri(vscode.Uri.file(path.join(
+ context.extensionPath,
+ 'web-resources/dist/cherry-markdown.css',
+ ),),),
+ 'cherry-markdown.js': webview.asWebviewUri(vscode.Uri.file(path.join(
+ context.extensionPath,
+ 'web-resources/dist/cherry-markdown.js',
+ ),),),
+ 'scripts/pinyin/pinyin_dist.js': webview.asWebviewUri(vscode.Uri.file(path.join(
+ context.extensionPath,
+ 'web-resources/scripts/pinyin/pinyin_dist.js',
+ ),),),
+ 'scripts/index-demo.js': webview.asWebviewUri(vscode.Uri.file(path.join(context.extensionPath, 'web-resources/scripts/index-demo.js'),),),
+ 'dist/fonts/ch-icon.woff': webview.asWebviewUri(vscode.Uri.file(path.join(
+ context.extensionPath,
+ 'web-resources/dist/fonts/ch-icon.woff',
+ ),),),
+ 'dist/fonts/ch-icon.woff2': webview.asWebviewUri(vscode.Uri.file(path.join(
+ context.extensionPath,
+ 'web-resources/dist/fonts/ch-icon.woff2',
+ ),),),
+ 'dist/fonts/ch-icon.ttf': webview.asWebviewUri(vscode.Uri.file(path.join(
+ context.extensionPath,
+ 'web-resources/dist/fonts/ch-icon.ttf',
+ ),),),
+ };
+
+ function getWebviewContent(pageResourceUrlsMap: any) {
+ return `
+
+
+
+
+
+ Cherry Editor - Markdown Editor
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `;
+ }
+
+ return getWebviewContent(pageResourceUrlsMap);
+};
diff --git a/vscodePlugin/src/demo.md b/vscodePlugin/src/demo.md
new file mode 100644
index 000000000..75540f483
--- /dev/null
+++ b/vscodePlugin/src/demo.md
@@ -0,0 +1,792 @@
+# 例子
+> [Github 地址](https://github.com/Tencent/cherry-markdown){target=_blank}
+
+- [basic](index.html){target=_blank}
+- [H5](h5.html){target=_blank}
+- [多实例](multiple.html){target=_blank}
+- [无 toolbar](notoolbar.html){target=_blank}
+- [纯预览模式](preview_only.html){target=_blank}
+- [注入](xss.html){target=_blank}
+- [API](api.html){target=_blank}
+- [图片所见即所得编辑尺寸](img.html){target=_blank}
+- [表格所见即所得编辑尺寸](table.html){target=_blank}
+- [标题自动序号](head_num.html){target=_blank}
+
+# Cherry Markdown { 简明手册 | jiǎn míng shǒu cè }
+
+[[toc]]
+
+# 基本语法
+
+---
+
+## 字体样式
+
+**说明**
+
+- 使用`*(或_)` 和 `**(或__)` 表示*斜体*和 **粗体**
+- 使用 `/` 表示 /下划线/ ,使用`~~` 表示~~删除线~~
+- 使用`^(或^^)`表示^上标^或^^下标^^
+- 使用 ! 号+数字 表示字体 !24 大! !12 小! [^专有语法提醒]
+- 使用两个(三个)!号+RGB 颜色 表示!!#ff0000 字体颜色!!(!!!#f9cb9c 背景颜色!!!)[^专有语法提醒]
+
+**示例**
+
+```
+[!!#ff0000 红色超链接!!](http://www.qq.com)
+[!!#ffffff !!!#000000 黑底白字超链接!!!!!](http://www.qq.com)
+[新窗口打开](http://www.qq.com){target=_blank}
+鞋子 !32 特大号!
+大头 ^`儿子`^ 和小头 ^^`爸爸`^^
+爱在~~西元前~~**当下**
+```
+
+**效果**
+[!!#ff0000 红色超链接!!](http://www.qq.com)
+[!!#ffffff !!!#000000 黑底白字超链接!!!!!](http://www.qq.com)
+[新窗口打开](http://www.qq.com){target=_blank}
+鞋子 !32 特大号!
+大头 ^`儿子`^ 和小头 ^^`爸爸`^^
+爱在~~西元前~~**当下**
+
+---
+
+## 标题设置
+
+**说明**
+
+- 在文字下方加 === 可使上一行文字变成一级标题
+- 在文字下方加 --- 可使上一行文字变成二级标题
+- 在行首加井号(#)表示不同级别的标题,例如:# H1, ##H2, ###H3
+
+---
+
+## 超链接
+
+**说明**
+
+- 使用 `[描述](URL)` 为文字增加外链接
+- 使用``插入一个链接
+- URL 会自动转成链接
+
+**示例**
+
+```
+这是 [腾讯网](https://www.qq.com) 的链接。
+这是 [一个引用的][引用一个链接] 的链接。
+这是一个包含中文的链接,中文
+直接识别成链接:https://www.qq.com?param=中文,中文 用空格结束
+[引用一个链接]
+[引用一个链接]: https://www.qq.com
+```
+
+**效果**
+这是 [腾讯网](https://www.qq.com) 的链接。
+这是 [一个引用的][引用一个链接] 的链接。
+这是一个包含中文的链接,中文
+直接识别成链接:https://www.qq.com?param=中文,中文 用空格结束
+[引用一个链接]
+[引用一个链接]: https://www.qq.com
+
+---
+
+## 无序列表
+
+**说明**
+
+- 在行首使用 \*,+,- 表示无序列表
+
+**示例**
+
+```
+- 无序列表项 一`默认`
+- 无序列表项 二
+ - 无序列表2.1
+ - 无序列表2.2
+- 无序列表项 三
+ + 无序列表3.1`空心圆`
+ + 无序列表3.1
+- 无序列表四
+ * 无序列表4.1`实心方块`
+ * 无序列表4.2
+
+```
+
+**效果**
+
+- 无序列表项 一`默认`
+- 无序列表项 二
+ - 无序列表2.1
+ - 无序列表2.2
+- 无序列表项 三
+ + 无序列表3.1`空心圆`
+ + 无序列表3.1
+- 无序列表四
+ * 无序列表4.1`实心方块`
+ * 无序列表4.2
+
+---
+
+## 有序列表
+
+**说明**
+
+- 在行首使用数字、字母、汉字和点表示有序列表
+
+**示例**
+
+```
+1. 有序列表项 一`阿拉伯数字`
+1. 有序列表项 二
+ I. 有序列表项 2.1`罗马数字`
+ I. 有序列表项 2.2
+ I. 有序列表项 2.3
+1. 有序列表 三
+ a. 有序列表3.1`希腊字母`
+ a. 有序列表3.2
+ a. 有序列表3.3
+1. 有序列表 四
+ 一. 有序列表4.1`中文数字`
+ 一. 有序列表4.2
+ 一. 有序列表4.3
+```
+
+**效果**
+
+1. 有序列表项 一`阿拉伯数字`
+1. 有序列表项 二
+ I. 有序列表项 2.1`罗马数字`
+ I. 有序列表项 2.2
+ I. 有序列表项 2.3
+1. 有序列表 三
+ a. 有序列表3.1`希腊字母`
+ a. 有序列表3.2
+ a. 有序列表3.3
+1. 有序列表 四
+ 一. 有序列表4.1`中文数字`
+ 一. 有序列表4.2
+ 一. 有序列表4.3
+
+---
+
+## 引用
+
+**说明**
+
+- 在行首使用 > 表示文字引用
+
+**示例**
+
+```
+> 野火烧不尽,春风吹又生
+```
+
+**效果**
+
+> 野火烧不尽,春风吹又生
+
+---
+
+## 行内代码
+
+**说明**
+
+- 使用 \`代码` 表示行内代码
+
+**示例**
+
+```
+让我们聊聊 `html`
+```
+
+**效果**
+让我们聊聊 `html`
+
+---
+
+## 代码块
+
+**说明**
+
+- 使用 三个` 表示代码块
+
+**效果**
+
+```
+ 这是一个代码块
+ 有两行
+```
+
+---
+
+## 插入图像
+
+**说明**
+
+- 使用 `![描述](图片链接地址)` 插入图像
+- 截图,在编辑器中粘贴(ctrl+V)也可以插入图像
+- 使用`![描述#宽度#高度#对齐方式](图片链接地址)` 可以调整图片大小[^专有语法提醒]
+
+**示例**
+
+```
+标准图片 ![一条dog#100px](images/demo-dog.png)
+设置图片大小(相对大小&绝对大小) ![一条dog#10%#50px](images/demo-dog.png)
+设置图片对齐方式:
+**左对齐+边框**
+![一条dog#auto#100px#left#border](images/demo-dog.png)
+**居中+边框+阴影**
+![一条dog#auto#100px#center#B#shadow](images/demo-dog.png)
+**右对齐+边框+阴影+圆角**
+![一条dog#auto#100px#right#B#S#radius](images/demo-dog.png)
+**浮动左对齐+边框+阴影+圆角**
+![一条dog#auto#100px#float-left#B#S#R](images/demo-dog.png)
+开心也是一天,不开心也是一天
+这样就过了两天,汪
+```
+
+**效果**
+标准图片 ![一条dog#100px](images/demo-dog.png)
+设置图片大小(相对大小&绝对大小) ![一条dog#10%#50px](images/demo-dog.png)
+设置图片对齐方式:
+**左对齐+边框**
+![一条dog#auto#100px#left#border](images/demo-dog.png)
+**居中+边框+阴影**
+![一条dog#auto#100px#center#B#shadow](images/demo-dog.png)
+**右对齐+边框+阴影+圆角**
+![一条dog#auto#100px#right#B#S#radius](images/demo-dog.png)
+**浮动左对齐+边框+阴影+圆角**
+![一条dog#auto#100px#float-left#B#S#R](images/demo-dog.png)
+开心也是一天,不开心也是一天
+这样就过了两天,汪
+
+
+> 属性释义:
+- 宽度:第一个 `#100px` 或 `#10%` 或 `#auto`
+- 高度:第二个 `#100px` 或 `#10%` 或 `#auto`
+- 左对齐:`#left`
+- 右对齐:`#right`
+- 居中对齐:`#center`
+- 悬浮左对齐:`#float-left`
+- 悬浮右对齐:`#float-right`
+- 边框:`#border` 或 `#B`
+- 阴影:`#shadow` 或 `#S`
+- 圆角:`#radius` 或 `#R`
+
+---
+
+# 高阶语法手册
+
+---
+
+## 目录
+
+**说明**
+
+- 使用`[[toc]]`,会自动生成一个页面目录,目录内容由一级、二级、三级标题组成
+
+---
+
+## 语法高亮
+
+**说明**
+
+- 在```后面指明语法名
+- 加强的代码块,支持四十一种编程语言的语法高亮的显示
+
+**效果**
+非代码示例:
+
+```
+$ sudo apt-get install vim-gnome
+```
+
+Python 示例:
+
+```python
+@requires_authorization
+def somefunc(param1='', param2=0):
+ '''A docstring'''
+ if param1 > param2: # interesting
+ print 'Greater'
+ return (param2 - param1 + 1) or None
+
+class SomeClass:
+ pass
+
+>>> message = '''interpreter
+... prompt'''
+```
+
+JavaScript 示例:
+
+```javascript
+/**
+ * nth element in the fibonacci series.
+ * @param n >= 0
+ * @return the nth element, >= 0.
+ */
+function fib(n) {
+ var a = 1,
+ b = 1;
+ var tmp;
+ while (--n >= 0) {
+ tmp = a;
+ a += b;
+ b = tmp;
+ }
+ return a;
+}
+
+document.write(fib(10));
+```
+
+---
+
+## checklist[^不通用提醒]
+
+**说明**
+
+- 输入`[ ]`或`[x]`,就会生成一个 checklist
+
+**示例**
+
+```
+- [ ] AAA
+- [x] BBB
+- [ ] CCC
+```
+
+**效果**
+
+- [ ] AAA
+- [x] BBB
+- [ ] CCC
+
+---
+
+## 公式[^不通用提醒]
+
+**说明**
+
+- 输入`$$`或`$`,就会生成一个公式
+- 访问 [MathJax](http://meta.math.stackexchange.com/questions/5020/mathjax-basic-tutorial-and-quick-reference) 参考更多使用方法
+
+**示例**
+
+```
+块级公式:$$
+\begin{aligned}
+P(B|A)&=\frac{P(AB)}{P(A)}\\
+P(\overline{B}|A)&=1-P(B|A)=1-\frac{P(AB)}{P(A)}
+\end{aligned}
+$$
+行内公式: $e=mc^2$
+```
+
+**效果**
+块级公式:$$
+\begin{aligned}
+P(B|A)&=\frac{P(AB)}{P(A)}\\
+P(\overline{B}|A)&=1-P(B|A)=1-\frac{P(AB)}{P(A)}
+\end{aligned}
+
+$$
+行内公式: $e=mc^2$
+
+
+-----
+
+
+
+## 插入音视频
+**说明**
+- 使用 `!v[描述](视频链接地址)` 插入视频
+ - 使用 `!v[描述](视频链接地址){poster=封面地址}` 插入视频并配上封面
+- 使用 `!audio[描述](视频链接地址)` 插入音频
+
+
+**示例**
+
+```
+这是个演示视频 !video[不带封面演示视频](images/demo.mp4)
+这是个演示视频 !video[带封面演示视频](images/demo.mp4){poster=images/demo-dog.png}
+这是个假音频!audio[描述](视频链接地址)
+```
+**效果**
+
+这是个演示视频 !video[不带封面演示视频](images/demo.mp4)
+这是个演示视频 !video[带封面演示视频](images/demo.mp4){poster=images/demo-dog.png}
+这是个假音频!audio[描述](视频链接地址)
+
+
+-----
+
+
+## 带对齐功能的表格
+**说明**
+- 一种比较通用的markdown表格语法
+
+
+**示例**
+```
+|项目(居中对齐)|价格(右对齐)|数量(左对齐)|
+|:-:|-:|:-|
+|计算机|¥1600|5|
+|手机机|¥12|50|
+```
+**效果**
+|项目(居中对齐)|价格(右对齐)|数量(左对齐)|
+|:-:|-:|:-|
+|计算机|¥1600|5|
+|手机机|¥12|50|
+
+-----
+
+
+## 流程图[^不通用提醒]
+**说明**
+- 访问[Mermaid 流程图](https://mermaid-js.github.io/mermaid/#/flowchart)参考具体使用方法。
+
+
+**效果**
+小明老婆让小明下班时买一斤包子,如果遇到卖西瓜的,买一个。
+
+左右结构
+```mermaid
+graph LR
+ A[公司] -->| 下 班 | B(菜市场)
+ B --> C{看见 卖西瓜的}
+ C -->|Yes| D[买一个包子]
+ C -->|No| E[买一斤包子]
+```
+上下结构
+```mermaid
+graph TD
+ A[公司] -->| 下 班 | B(菜市场)
+ B --> C{看见 卖西瓜的}
+ C -->|Yes| D[买一个包子]
+ C -->|No| E[买一斤包子]
+```
+
+
+-----
+
+
+
+## 时序图[^不通用提醒]
+**说明**
+- 访问[Mermaid 时序图](https://mermaid-js.github.io/mermaid/#/sequenceDiagram)参考具体使用方法
+
+
+**效果**
+```mermaid
+sequenceDiagram
+A-->A: 文本1
+A->>B: 文本2
+loop 循环1
+loop 循环2
+A->B: 文本3
+end
+loop 循环3
+B -->>A: 文本4
+end
+B -->> B: 文本5
+end
+```
+
+
+-----
+
+
+
+## 状态图[^不通用提醒]
+**说明**
+- 访问[Mermaid 状态图](https://mermaid-js.github.io/mermaid/#/stateDiagram)参考具体使用方法
+
+
+**效果**
+```mermaid
+stateDiagram
+[*] --> A
+A --> B
+A --> C
+state A {
+ [*] --> D
+ D --> [*]
+}
+B --> [*]
+C --> [*]
+```
+
+
+-----
+
+
+
+## UML图[^不通用提醒]
+**说明**
+- 访问[Mermaid UML图](https://mermaid-js.github.io/mermaid/#/classDiagram)参考具体使用方法
+
+
+**效果**
+```mermaid
+classDiagram
+Base <|-- One
+Base <|-- Two
+Base : +String name
+Base: +getName()
+Base: +setName(String name)
+class One{
+ +String newName
+ +getNewName()
+}
+class Two{
+ -int id
+ -getId()
+}
+```
+
+
+-----
+
+
+
+## 饼图[^不通用提醒]
+**说明**
+- 访问[Mermaid 饼图](https://mermaid-js.github.io/mermaid/#/pie)参考具体使用方法
+
+
+**效果**
+```mermaid
+pie
+title 饼图
+"A" : 40
+"B" : 30
+"C" : 20
+"D" : 10
+```
+
+
+-----
+
+
+
+## 注释[^不通用提醒]
+**说明**
+- 使用中括号+冒号([]:)生成单行注释
+- 使用中括号+尖号+冒号([^]:)生成多行注释
+- 多行注释以连续两次回车结束
+
+
+**示例**
+```
+下面是一行单行注释
+[注释摘要]: 这是一段注释,不会显示到页面上
+上面面是一行单行注释
+下面是多行注释
+[^注释摘要]: 这是一段多行注释,不会显示到页面上
+可以换行
+ 可以缩进
+以两次回车结束
+
+上面是多行注释
+```
+**效果**
+下面是一行单行注释
+[注释摘要]: 这是一段注释,不会显示到页面上
+上面面是一行单行注释
+下面是多行注释
+[^注释摘要]: 这是一段多行注释,不会显示到页面上
+可以换行
+ 可以缩进
+以两次回车结束
+
+上面是多行注释
+
+
+-----
+
+
+
+## 脚注[^不通用提醒]
+**说明**
+- 在段落中引用多行注释即会生成脚注
+- 脚注中括号中的数字以引用脚注的顺序自动生成
+- 点击脚注的数字可以跳转到脚注详情或回到引用脚注位置
+
+
+**示例**
+```
+这里需要一个脚注[^脚注别名1],另外这里也需要一个脚注[^another]。
+[^脚注别名1]: 无论脚注内容写在哪里,脚注的内容总会显示在页面最底部
+以两次回车结束
+
+[^another]: 另外,脚注里也可以使用一些简单的markdown语法
+>比如 !!#ff0000 这里!!有一段**引用**
+
+```
+**效果**
+这里需要一个脚注[^脚注别名1],另外这里也需要一个脚注[^another]。
+[^脚注别名1]: 无论脚注内容写在哪里,脚注的内容总会显示在页面最底部
+以两次回车结束
+
+[^another]: 另外,脚注里也可以使用一些简单的markdown语法
+>比如 !!#ff0000 这里!!有一段**引用**
+
+
+-----
+
+
+# 编辑器操作能力
+
+
+-----
+
+
+## 通过快捷按钮修改字体样式
+![bubble menu](images/feature_font.png)
+
+
+-----
+
+
+
+## 复制html内容,粘贴成markdown
+**说明**
+- 粘贴html内容时会自动转成markdown,也可以选择粘贴为纯文本格式
+- 可以拖拽调整预览区域的宽度
+
+
+![copy and paste](images/feature_copy.gif)
+
+
+-----
+
+
+## 快捷键
+| 功能| 按键|
+|--|--|
+|1级标题| `Ctrl + 1`|
+|2级标题| `Ctrl + 2`|
+|3级标题| `Ctrl + 3`|
+|4级标题| `Ctrl + 4`|
+|5级标题| `Ctrl + 5`|
+|6级标题| `Ctrl + 6`|
+|加粗| `Ctrl + b`|
+|斜体| `Ctrl + i` |
+|插入链接| `Ctrl + l` |
+|插入代码块| `Ctrl + k` |
+|插入图片| `Ctrl + g` |
+|插入公式| `Ctrl + m` |
+
+
+
+## 协议
+```
+/**
+ * Tencent is pleased to support the open source community by making CherryMarkdown available.
+ *
+ * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
+ * The below software in this distribution may have been modified by THL A29 Limited ("Tencent Modifications").
+ *
+ * All Tencent Modifications are Copyright (C) THL A29 Limited.
+ *
+ * CherryMarkdown is licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+```
+
+
+
+[^专有语法提醒]: 该语法是**CherryMarkdown专有语法**,可能无法在其他markdown平台上使用该语法
+
+[^不通用提醒]: 该语法不是markdown通用语法,无法保证在其他markdown平台上进行正确渲染
+
+
+# 特性展示
+
+## 语法特性
+
+> 支持了所有常用的、通用的语法,除此之外我们还支持了一些有意思的语法
+
+### 特性 1:图片缩放、对齐、引用
+
+#### 语法
+
+`![img #宽度#高度#对齐方式][图片URL或引用]`
+
+> 其中,`宽度`、`高度`支持:绝对像素值(比如200px)、相对外层容器百分比(比如50%),
+`对齐方式`候选值有:左对齐(缺省)、右对齐(right)、居中(center)、悬浮左、右对齐(float-left/right)
+![图片尺寸](images/feature_image_size.png)
+
+-----
+
+### 特性 2:根据表格内容生成图表
+![表格图表](images/feature_table_chart.png)
+
+-----
+
+### 特性 3:字体颜色、字体大小
+![字体样式](images/feature_font.png)
+
+------
+
+## 功能特性
+
+### 特性 1:复制Html粘贴成MD语法
+![html转md](images/feature_copy.gif)
+
+#### 使用场景
+
+- Markdown初学者快速熟悉MD语法的一个途径
+- 为调用方提供一个历史富文本数据迁成Markdown数据的方法
+
+----
+
+### 特性 2:经典换行&常规换行
+![br](images/feature_br.gif)
+
+#### 使用场景
+
+团队对markdown源码有最大宽度限制?一键切回经典换行(两个及以上连续换行才算一个换行)
+
+-----
+
+### 特性 3: 多光标编辑
+![br](images/feature_cursor.gif)
+
+#### 使用场景
+
+想要批量修改?可以试试多光标编辑(快捷键、搜索多光标选中等功能正在开发中)
+
+### 特性 4:图片尺寸
+![wysiwyg](images/feature_image_wysiwyg.gif)
+
+### 特性 5:导出
+![wysiwyg](images/feature_export.png)
+
+-------
+
+## 性能特性
+
+### 局部渲染
+
+> CherryMarkdown会判断用户到底变更了哪个段落,做到只渲染变更的段落,从而提升修改时的渲染性能
+
+![wysiwyg](images/feature_myers.png)
+
+### 局部更新
+
+> CherryMarkdown利用virtual dom机制实现对预览区域需要变更的内容进行局部更新的功能,从而减少了浏览器Dom操作,提高了修改时预览内容更新的性能
+
+![wysiwyg](images/feature_vdom.gif)
diff --git a/vscodePlugin/src/extension.ts b/vscodePlugin/src/extension.ts
new file mode 100644
index 000000000..d515b97d3
--- /dev/null
+++ b/vscodePlugin/src/extension.ts
@@ -0,0 +1,171 @@
+import * as vscode from 'vscode';
+import * as path from 'path';
+import { getWebviewContent } from './webview';
+
+let cherryPanel: vscode.WebviewPanel; // 保存预览窗口的webview实例
+let isCherryPanelInit: boolean = false;
+let extensionPath: string = '';
+let targetDocument: vscode.TextEditor;
+let disableScrollTrigger: boolean = false; // true:滚动时不往webview发送滚动事件,反之发送
+let disableEditTrigger: boolean = false; // true:变更内容时不往webview发送内容变更事件,反之发送
+let cherryTheme: string | undefined = vscode.workspace.getConfiguration('cherryMarkdown').get('theme'); // 缓存主题
+export function activate(context: vscode.ExtensionContext) {
+ extensionPath = context.extensionPath;
+ // 注册命令
+ const disposable = vscode.commands.registerCommand(
+ 'cherrymarkdown.preview',
+ () => {
+ triggerEditorContentChange();
+ }
+ );
+
+ context.subscriptions.push(disposable);
+
+ // 打开文件的时候触发
+ vscode.workspace.onDidOpenTextDocument(() => {
+ vscode.commands.executeCommand('cherrymarkdown.preview');
+ });
+
+ // 切换文件的时候更新预览区域内容
+ vscode.window.onDidChangeActiveTextEditor((e) => {
+ if (e?.document) {
+ triggerEditorContentChange();
+ // 如果打开的不是md文件,则让cherry强制进入预览模式
+ if (e.document.languageId !== 'markdown' && targetDocument) {
+ cherryPanel.webview.postMessage({ cmd: 'disable-edit', data: {} });
+ } else {
+ cherryPanel.webview.postMessage({ cmd: 'enable-edit', data: {} });
+ }
+ }
+ });
+
+ // 当修改文档内容的时候更新预览区域内容,如果已经关闭预览了,则不需要重新打开预览
+ vscode.workspace.onDidChangeTextDocument((e) => {
+ if (isCherryPanelInit && e?.document && !disableEditTrigger) {
+ triggerEditorContentChange();
+ }
+ });
+
+ // 滚动的时候让预览区域同步滚动
+ vscode.window.onDidChangeTextEditorVisibleRanges((e) => {
+ if (!isCherryPanelInit) {
+ return true;
+ }
+ disableScrollTrigger || cherryPanel.webview.postMessage({ cmd: 'editor-scroll', data: e.visibleRanges[0].start.line });
+ });
+}
+
+// this method is called when your extension is deactivated
+export function deactivate() {}
+
+/**
+ * 获取当前文件的信息
+ * @returns
+ */
+const getMarkdownFileInfo = () => {
+ let currentEditor = vscode.window.activeTextEditor;
+ // const currentLine = currentEditor?.visibleRanges[0].start.line;
+ let currentDoc = currentEditor?.document;
+ let currentText = '';
+ let currentTitle = '';
+ if (currentDoc?.languageId !== 'markdown' && targetDocument.document.languageId === 'markdown') {
+ currentEditor = targetDocument;
+ currentDoc = targetDocument.document;
+ }
+ if (currentDoc?.languageId === 'markdown') {
+ if (currentEditor) {
+ targetDocument = currentEditor;
+ }
+ currentText = currentDoc?.getText() || '';
+ currentTitle = path.basename(currentDoc?.fileName) || '';
+ }
+ currentTitle = currentTitle ? `预览 ${currentTitle} by cherry-markdown` : '不支持当前文件 by cherry-markdown';
+ const theme = cherryTheme ? cherryTheme : vscode.workspace.getConfiguration('cherryMarkdown').get('theme');
+ const mdInfo = { text: currentText, theme };
+ return { mdInfo, currentTitle };
+};
+
+/**
+ * 初始化cherry预览窗口
+ */
+const initCherryPanel = () => {
+ const { mdInfo, currentTitle } = getMarkdownFileInfo();
+ cherryPanel = vscode.window.createWebviewPanel(
+ 'cherrymarkdown.preview',
+ currentTitle,
+ vscode.ViewColumn.Two,
+ {
+ enableScripts: true,
+ retainContextWhenHidden: true,
+ }
+ );
+ cherryPanel.webview.html = getWebviewContent(mdInfo, cherryPanel, extensionPath);
+ isCherryPanelInit = true;
+
+ initCherryPanelEvent();
+};
+
+// eslint-disable-next-line no-unused-vars, no-undef
+let scrollTimeOut: NodeJS.Timeout;
+// eslint-disable-next-line no-unused-vars, no-undef
+let editTimeOut: NodeJS.Timeout;
+const initCherryPanelEvent = () => {
+ cherryPanel?.webview?.onDidReceiveMessage((e) => {
+ const { type, data } = e;
+ switch (type) {
+ // 滚动的时候同步滚动
+ case 'preview-scroll':
+ disableScrollTrigger = true;
+ // eslint-disable-next-line no-case-declarations
+ const pos = new vscode.Position(data, 0);
+ // eslint-disable-next-line no-case-declarations
+ const range = new vscode.Range(pos, pos);
+ targetDocument.revealRange(range, vscode.TextEditorRevealType.AtTop);
+ scrollTimeOut && clearTimeout(scrollTimeOut);
+ scrollTimeOut = setTimeout(() => {
+ disableScrollTrigger = false;
+ }, 500);
+ return;
+ // 变更主题的时候同时更新配置
+ case 'change-theme':
+ cherryTheme = data;
+ vscode.workspace.getConfiguration('cherryMarkdown').update('theme', data, true);
+ break;
+ // 内容变更的时候同时更新对应的文档内容
+ case 'cherry-change':
+ disableEditTrigger = true;
+ targetDocument.edit((editBuilder) => {
+ const endNum = targetDocument.document.lineCount + 1;
+ const end = new vscode.Position(endNum, 0);
+ editBuilder.replace(new vscode.Range(new vscode.Position(0, 0), end), data.markdown);
+ });
+ editTimeOut && clearTimeout(editTimeOut);
+ editTimeOut = setTimeout(() => {
+ disableEditTrigger = false;
+ }, 500);
+ break;
+ case 'tips':
+ vscode.window.showInformationMessage(data, 'OK');
+ break;
+ }
+ });
+
+ cherryPanel?.onDidDispose(() => {
+ isCherryPanelInit = false;
+ });
+};
+
+/**
+ * 向预览区发送vscode编辑区内容变更的消息
+ */
+const triggerEditorContentChange = () => {
+ if (isCherryPanelInit) {
+ const { mdInfo, currentTitle } = getMarkdownFileInfo();
+ cherryPanel.title = currentTitle;
+ cherryPanel.webview.postMessage({ cmd: 'editor-change', data: mdInfo });
+ } else {
+ if (vscode.window.activeTextEditor?.document?.languageId === 'markdown') {
+ initCherryPanel();
+ }
+ }
+};
diff --git a/vscodePlugin/src/test/runTest.ts b/vscodePlugin/src/test/runTest.ts
new file mode 100644
index 000000000..a629e3e2e
--- /dev/null
+++ b/vscodePlugin/src/test/runTest.ts
@@ -0,0 +1,23 @@
+import * as path from 'path';
+
+import { runTests } from 'vscode-test';
+
+async function main() {
+ try {
+ // The folder containing the Extension Manifest package.json
+ // Passed to `--extensionDevelopmentPath`
+ const extensionDevelopmentPath = path.resolve(__dirname, '../../');
+
+ // The path to test runner
+ // Passed to --extensionTestsPath
+ const extensionTestsPath = path.resolve(__dirname, './suite/index');
+
+ // Download VS Code, unzip it and run the integration test
+ await runTests({ extensionDevelopmentPath, extensionTestsPath });
+ } catch (err) {
+ console.error('Failed to run tests');
+ process.exit(1);
+ }
+}
+
+main();
diff --git a/vscodePlugin/src/test/suite/extension.test.ts b/vscodePlugin/src/test/suite/extension.test.ts
new file mode 100644
index 000000000..17e2eab2a
--- /dev/null
+++ b/vscodePlugin/src/test/suite/extension.test.ts
@@ -0,0 +1,15 @@
+import * as assert from 'assert';
+
+// You can import and use all API from the 'vscode' module
+// as well as import your extension to test it
+import * as vscode from 'vscode';
+// import * as myExtension from '../../extension';
+
+suite('Extension Test Suite', () => {
+ vscode.window.showInformationMessage('Start all tests.');
+
+ test('Sample test', () => {
+ assert.strictEqual(-1, [1, 2, 3].indexOf(5));
+ assert.strictEqual(-1, [1, 2, 3].indexOf(0));
+ });
+});
diff --git a/vscodePlugin/src/test/suite/index.ts b/vscodePlugin/src/test/suite/index.ts
new file mode 100644
index 000000000..4caddd0ab
--- /dev/null
+++ b/vscodePlugin/src/test/suite/index.ts
@@ -0,0 +1,38 @@
+import * as path from 'path';
+import * as Mocha from 'mocha';
+import * as glob from 'glob';
+
+export function run(): Promise {
+ // Create the mocha test
+ const mocha = new Mocha({
+ ui: 'tdd',
+ color: true,
+ });
+
+ const testsRoot = path.resolve(__dirname, '..');
+
+ return new Promise((c, e) => {
+ glob('**/**.test.js', { cwd: testsRoot }, (err, files) => {
+ if (err) {
+ return e(err);
+ }
+
+ // Add files to the test suite
+ files.forEach(f => mocha.addFile(path.resolve(testsRoot, f)));
+
+ try {
+ // Run the mocha test
+ mocha.run((failures) => {
+ if (failures > 0) {
+ e(new Error(`${failures} tests failed.`));
+ } else {
+ c();
+ }
+ });
+ } catch (err) {
+ console.error(err);
+ e(err);
+ }
+ });
+ });
+}
diff --git a/vscodePlugin/src/webview.ts b/vscodePlugin/src/webview.ts
new file mode 100644
index 000000000..195700a67
--- /dev/null
+++ b/vscodePlugin/src/webview.ts
@@ -0,0 +1,51 @@
+import * as vscode from 'vscode';
+import * as path from 'path';
+
+/**
+ * 返回webview需要的html页面
+ * @param mdInfo MD源码 和 一些配置信息
+ * @param currentPanel WebviewPanel实例
+ * @param extensionPath 静态资源路径
+ * @returns string
+ */
+export function getWebviewContent(mdInfo: object, currentPanel: vscode.WebviewPanel, extensionPath: string) {
+ const pageResourceUrlsMap = {
+ 'index.css': currentPanel.webview.asWebviewUri(vscode.Uri.file(path.join(extensionPath, 'web-resources/index.css'))),
+ 'cherry-markdown.css': currentPanel.webview.asWebviewUri(vscode.Uri.file(path.join(extensionPath, 'web-resources/dist/cherry-markdown.min.css'))),
+ 'cherry-markdown.js': currentPanel.webview.asWebviewUri(vscode.Uri.file(path.join(extensionPath, 'web-resources/dist/cherry-markdown.min.js'))),
+ 'scripts/pinyin/pinyin_dist.js': currentPanel.webview.asWebviewUri(vscode.Uri.file(path.join(extensionPath, 'web-resources/scripts/pinyin/pinyin_dist.js'))),
+ 'scripts/index.js': currentPanel.webview.asWebviewUri(vscode.Uri.file(path.join(extensionPath, 'dist/index.js'))),
+ 'scripts/index.css': currentPanel.webview.asWebviewUri(vscode.Uri.file(path.join(extensionPath, 'web-resources/scripts/index.css'))),
+ 'dist/fonts/ch-icon.woff': currentPanel.webview.asWebviewUri(vscode.Uri.file(path.join(extensionPath, 'web-resources/dist/fonts/ch-icon.woff'))),
+ 'dist/fonts/ch-icon.woff2': currentPanel.webview.asWebviewUri(vscode.Uri.file(path.join(extensionPath, 'web-resources/dist/fonts/ch-icon.woff2'))),
+ 'dist/fonts/ch-icon.ttf': currentPanel.webview.asWebviewUri(vscode.Uri.file(path.join(extensionPath, 'web-resources/dist/fonts/ch-icon.ttf'))),
+ };
+ return `
+
+
+
+
+
+ Cherry Editor - Markdown Editor
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `;
+}
diff --git a/vscodePlugin/tsconfig.json b/vscodePlugin/tsconfig.json
new file mode 100644
index 000000000..b65c74510
--- /dev/null
+++ b/vscodePlugin/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "compilerOptions": {
+ "module": "commonjs",
+ "target": "es6",
+ "outDir": "out",
+ "lib": [
+ "es6"
+ ],
+ "sourceMap": true,
+ "rootDir": "src",
+ "strict": true /* enable all strict type-checking options */
+ /* Additional Checks */
+ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
+ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
+ // "noUnusedParameters": true, /* Report errors on unused parameters. */
+ },
+ "exclude": [
+ "node_modules",
+ ".vscode-test"
+ ]
+}
diff --git a/vscodePlugin/vsc-extension-quickstart.md b/vscodePlugin/vsc-extension-quickstart.md
new file mode 100644
index 000000000..b510bff34
--- /dev/null
+++ b/vscodePlugin/vsc-extension-quickstart.md
@@ -0,0 +1,42 @@
+# Welcome to your VS Code Extension
+
+## What's in the folder
+
+* This folder contains all of the files necessary for your extension.
+* `package.json` - this is the manifest file in which you declare your extension and command.
+ * The sample plugin registers a command and defines its title and command name. With this information VS Code can show the command in the command palette. It doesn’t yet need to load the plugin.
+* `src/extension.ts` - this is the main file where you will provide the implementation of your command.
+ * The file exports one function, `activate`, which is called the very first time your extension is activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`.
+ * We pass the function containing the implementation of the command as the second parameter to `registerCommand`.
+
+## Get up and running straight away
+
+* Press `F5` to open a new window with your extension loaded.
+* Run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`.
+* Set breakpoints in your code inside `src/extension.ts` to debug your extension.
+* Find output from your extension in the debug console.
+
+## Make changes
+
+* You can relaunch the extension from the debug toolbar after changing code in `src/extension.ts`.
+* You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes.
+
+
+## Explore the API
+
+* You can open the full set of our API when you open the file `node_modules/@types/vscode/index.d.ts`.
+
+## Run tests
+
+* Open the debug viewlet (`Ctrl+Shift+D` or `Cmd+Shift+D` on Mac) and from the launch configuration dropdown pick `Extension Tests`.
+* Press `F5` to run the tests in a new window with your extension loaded.
+* See the output of the test result in the debug console.
+* Make changes to `src/test/suite/extension.test.ts` or create new test files inside the `test/suite` folder.
+ * The provided test runner will only consider files matching the name pattern `**.test.ts`.
+ * You can create folders inside the `test` folder to structure your tests any way you want.
+
+## Go further
+
+ * Reduce the extension size and improve the startup time by [bundling your extension](https://code.visualstudio.com/api/working-with-extensions/bundling-extension).
+ * [Publish your extension](https://code.visualstudio.com/api/working-with-extensions/publishing-extension) on the VSCode extension marketplace.
+ * Automate builds by setting up [Continuous Integration](https://code.visualstudio.com/api/working-with-extensions/continuous-integration).
diff --git a/vscodePlugin/web-resources/dist/cherry-markdown.min.css b/vscodePlugin/web-resources/dist/cherry-markdown.min.css
new file mode 100644
index 000000000..fc70c19f2
--- /dev/null
+++ b/vscodePlugin/web-resources/dist/cherry-markdown.min.css
@@ -0,0 +1 @@
+.cherry *::-webkit-scrollbar{height:7px;width:7px;background:rgba(0,0,0,0)}.cherry *::-webkit-scrollbar:hover{background:rgba(128,128,128,.1)}.cherry *::-webkit-scrollbar-thumb{background:#d3d7da;-webkit-border-radius:6px}.cherry *::-webkit-scrollbar-thumb:hover{background:rgba(0,0,0,.6)}.cherry *::-webkit-scrollbar-corner{background:rgba(0,0,0,0)}@font-face{font-family:"ch-icon";src:url("./fonts/ch-icon.eot");src:url("./fonts/ch-icon.eot?#iefix") format("eot"),url("./fonts/ch-icon.woff2") format("woff2"),url("./fonts/ch-icon.woff") format("woff"),url("./fonts/ch-icon.ttf") format("truetype"),url("./fonts/ch-icon.svg#ch-icon") format("svg");font-weight:normal;font-style:normal}.ch-icon:before{display:inline-block;font-family:"ch-icon";font-style:normal;font-weight:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.ch-icon-list:before{content:""}.ch-icon-check:before{content:""}.ch-icon-square:before{content:""}.ch-icon-bold:before{content:""}.ch-icon-code:before{content:""}.ch-icon-color:before{content:""}.ch-icon-header:before{content:""}.ch-icon-image:before{content:""}.ch-icon-italic:before{content:""}.ch-icon-link:before{content:""}.ch-icon-ol:before{content:""}.ch-icon-size:before{content:""}.ch-icon-strike:before{content:""}.ch-icon-table:before{content:""}.ch-icon-ul:before{content:""}.ch-icon-underline:before{content:""}.ch-icon-word:before{content:""}.ch-icon-blockquote:before{content:""}.ch-icon-font:before{content:""}.ch-icon-insertClass:before{content:""}.ch-icon-insertFlow:before{content:""}.ch-icon-insertFormula:before{content:""}.ch-icon-insertGantt:before{content:""}.ch-icon-insertGraph:before{content:""}.ch-icon-insertPie:before{content:""}.ch-icon-insertSeq:before{content:""}.ch-icon-insertState:before{content:""}.ch-icon-line:before{content:""}.ch-icon-preview:before{content:""}.ch-icon-previewClose:before{content:""}.ch-icon-toc:before{content:""}.ch-icon-sub:before{content:""}.ch-icon-sup:before{content:""}.ch-icon-h1:before{content:""}.ch-icon-h2:before{content:""}.ch-icon-h3:before{content:""}.ch-icon-h4:before{content:""}.ch-icon-h5:before{content:""}.ch-icon-h6:before{content:""}.ch-icon-video:before{content:""}.ch-icon-insert:before{content:""}.ch-icon-little_table:before{content:""}.ch-icon-pdf:before{content:""}.ch-icon-checklist:before{content:""}.ch-icon-close:before{content:""}.ch-icon-fullscreen:before{content:""}.ch-icon-minscreen:before{content:""}.ch-icon-insertChart:before{content:""}.ch-icon-question:before{content:""}.ch-icon-settings:before{content:""}.ch-icon-ok:before{content:""}.ch-icon-br:before{content:""}.ch-icon-normal:before{content:""}.ch-icon-undo:before{content:""}.ch-icon-redo:before{content:""}.ch-icon-copy:before{content:""}.ch-icon-phone:before{content:""}.ch-icon-cherry-table-delete:before{content:""}.ch-icon-cherry-table-insert-bottom:before{content:""}.ch-icon-cherry-table-insert-left:before{content:""}.ch-icon-cherry-table-insert-right:before{content:""}.ch-icon-cherry-table-insert-top:before{content:""}.ch-icon-sort-s:before{content:""}.ch-icon-pinyin:before{content:""}.ch-icon-create:before{content:""}.ch-icon-download:before{content:""}.ch-icon-edit:before{content:""}.ch-icon-export:before{content:""}.ch-icon-folder-open:before{content:""}.ch-icon-folder:before{content:""}.ch-icon-help:before{content:""}.ch-icon-pen-fill:before{content:""}.ch-icon-pen:before{content:""}.ch-icon-search:before{content:""}.ch-icon-tips:before{content:""}.ch-icon-warn:before{content:""}.cherry-markdown{word-break:break-all}.cherry-markdown h1,.cherry-markdown h2,.cherry-markdown h3,.cherry-markdown h4,.cherry-markdown h5,.cherry-markdown h6,.cherry-markdown .h1,.cherry-markdown .h2,.cherry-markdown .h3,.cherry-markdown .h4,.cherry-markdown .h5,.cherry-markdown .h6{font-family:inherit;font-weight:700;line-height:1.1;color:inherit}.cherry-markdown h1 small,.cherry-markdown h2 small,.cherry-markdown h3 small,.cherry-markdown h4 small,.cherry-markdown h5 small,.cherry-markdown h6 small,.cherry-markdown .h1 small,.cherry-markdown .h2 small,.cherry-markdown .h3 small,.cherry-markdown .h4 small,.cherry-markdown .h5 small,.cherry-markdown .h6 small,.cherry-markdown h1 .small,.cherry-markdown h2 .small,.cherry-markdown h3 .small,.cherry-markdown h4 .small,.cherry-markdown h5 .small,.cherry-markdown h6 .small,.cherry-markdown .h1 .small,.cherry-markdown .h2 .small,.cherry-markdown .h3 .small,.cherry-markdown .h4 .small,.cherry-markdown .h5 .small,.cherry-markdown .h6 .small{font-weight:normal;line-height:1;color:#999}.cherry-markdown h1,.cherry-markdown h2,.cherry-markdown h3{margin-top:30px;margin-bottom:16px}.cherry-markdown h1 small,.cherry-markdown h2 small,.cherry-markdown h3 small,.cherry-markdown h1 .small,.cherry-markdown h2 .small,.cherry-markdown h3 .small{font-size:65%}.cherry-markdown h4,.cherry-markdown h5,.cherry-markdown h6{margin-top:12px;margin-bottom:12px}.cherry-markdown h4 small,.cherry-markdown h5 small,.cherry-markdown h6 small,.cherry-markdown h4 .small,.cherry-markdown h5 .small,.cherry-markdown h6 .small{font-size:75%}.cherry-markdown h1,.cherry-markdown .h1{font-size:2em}.cherry-markdown h2,.cherry-markdown .h2{font-size:1.5em}.cherry-markdown h3,.cherry-markdown .h3{font-size:1.25em}.cherry-markdown h4,.cherry-markdown .h4{font-size:1em}.cherry-markdown h5,.cherry-markdown .h5{font-size:.875em}.cherry-markdown h6,.cherry-markdown .h6{font-size:.85em}.cherry-markdown b,.cherry-markdown strong{font-weight:bold}.cherry-markdown ul,.cherry-markdown ol{padding-left:24px;margin-bottom:16px}.cherry-markdown ul ul,.cherry-markdown ul ol,.cherry-markdown ol ul,.cherry-markdown ol ol{margin-bottom:0}.cherry-markdown ul li,.cherry-markdown ol li{list-style:inherit}.cherry-markdown ul li p,.cherry-markdown ol li p{margin:0}.cherry-markdown div ul,.cherry-markdown div ol{margin-bottom:0}.cherry-markdown hr{height:0;border:0;border-top:1px solid #dfe6ee;margin:16px 0;box-sizing:content-box;overflow:visible}.cherry-markdown table{border-collapse:collapse}.cherry-markdown table th,.cherry-markdown table td{border:1px solid #dfe6ee;padding:.2em .4em;min-width:100px}.cherry-markdown table th{background-color:#eee}.cherry-markdown a{color:#3582fb}.cherry-markdown a:hover{color:#056bad}.cherry-markdown em{font-style:italic}.cherry-markdown sup{vertical-align:super}.cherry-markdown sub{vertical-align:sub}.cherry-markdown figure{overflow-x:auto}.cherry-markdown blockquote{color:#6d6e6f;padding:10px 15px;border-left:10px solid #d6dbdf;background:rgba(102,128,153,.05)}.cherry-markdown p,.cherry-markdown pre,.cherry-markdown blockquote,.cherry-markdown table{margin:0 0 16px}.cherry-markdown pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f6f8fa;border-radius:6px}.cherry-markdown .prettyprint{min-width:500px;display:inline-block;background:#00212b;font-family:Menlo,"Bitstream Vera Sans Mono","DejaVu Sans Mono",Monaco,Consolas,monospace;border:0 !important}.cherry-markdown .pln{color:#dfe6ee}.cherry-markdown .str{color:#ffaf21}.cherry-markdown .kwd{color:#f85353}.cherry-markdown ol.linenums{margin-top:0;margin-bottom:0;color:#969896}.cherry-markdown li.L0,.cherry-markdown li.L1,.cherry-markdown li.L2,.cherry-markdown li.L3,.cherry-markdown li.L4,.cherry-markdown li.L5,.cherry-markdown li.L6,.cherry-markdown li.L7,.cherry-markdown li.L8,.cherry-markdown li.L9{padding-left:1em;background-color:#00212b;list-style-type:decimal}@media screen{.cherry-markdown .cherry-markdown .com{color:#969896}.cherry-markdown .cherry-markdown .typ{color:#81a2be}.cherry-markdown .cherry-markdown .lit{color:#de935f}.cherry-markdown .cherry-markdown .pun{color:#c5c8c6}.cherry-markdown .cherry-markdown .opn{color:#c5c8c6}.cherry-markdown .cherry-markdown .clo{color:#c5c8c6}.cherry-markdown .cherry-markdown .tag{color:#c66}.cherry-markdown .cherry-markdown .atn{color:#de935f}.cherry-markdown .cherry-markdown .atv{color:#8abeb7}.cherry-markdown .cherry-markdown .dec{color:#de935f}.cherry-markdown .cherry-markdown .var{color:#c66}.cherry-markdown .cherry-markdown .fun{color:#81a2be}}.cherry-markdown div[data-type=codeBlock]{display:inline-block;width:100%;box-sizing:border-box;border-radius:2px;margin-bottom:16px;font-size:14px;overflow-x:auto}.cherry-markdown div[data-type=codeBlock]>pre{margin:0}.cherry-markdown div[data-type=codeBlock]>pre code[class*=language-]{counter-reset:line}.cherry-markdown div[data-type=codeBlock]>pre code[class*=language-].wrap{white-space:pre-wrap}.cherry-markdown div[data-type=codeBlock]>pre code[class*=language-] .code-line{display:inline-block;position:relative;padding-left:3em;height:1.3em;line-height:2em}.cherry-markdown div[data-type=codeBlock]>pre code[class*=language-] .code-line:before{counter-increment:line;content:counter(line);margin-right:1em;position:absolute;left:0}.cherry-markdown div[data-type=codeBlock]>pre code[class*=language-] .code-line:last-child{margin-bottom:0}.cherry-markdown :not(pre)>code{padding:.1em;border-radius:.3em;white-space:normal;color:#f85353;background-color:#e5e5e5}[data-inline-code-theme=black] .cherry-markdown :not(pre)>code{color:#3f4a56;background-color:#e5e5e5}.cherry-markdown a.anchor:before{content:"§";text-decoration:none;width:15px;font-size:.5em;vertical-align:middle;display:inline-block;text-align:center;margin-left:-15px}.cherry-markdown .toc{margin-bottom:16px;padding-left:0}.cherry-markdown .toc .toc-title{font-size:24px;margin-bottom:5px}.cherry-markdown .toc .toc-li{border-bottom:1px ridge #dfe6ee;list-style:none}.cherry-markdown .toc .toc-li a{text-decoration:none;color:#3f4a56}.cherry-markdown .toc .toc-li a:hover{color:#056bad}.cherry-markdown .check-list-item{list-style:none}.cherry-markdown .check-list-item .ch-icon{margin:0 6px 0 -20px}.cherry-markdown .footnote:not(a){padding-top:20px;border-top:1px solid #dfe6ee;margin-top:50px}.cherry-markdown .footnote:not(a) .footnote-title{font-size:20px;margin-top:-38px;background-color:#f8fafb;width:60px;margin-bottom:16px}.cherry-markdown .footnote:not(a) .one-footnote{color:#6d6e6f;margin-bottom:16px;border-bottom:1px dotted #dfe6ee}.cherry-markdown .cherry-table-container{max-width:100%;overflow-x:auto}.cherry-markdown .cherry-table-container .cherry-table th,.cherry-markdown .cherry-table-container .cherry-table td{border:1px solid #dfe6ee;padding:.2em .4em;min-width:100px}.cherry-markdown .cherry-table-container .cherry-table th{white-space:nowrap}.cherry-markdown mjx-assistive-mml{position:absolute;top:0;left:0;clip:rect(1px, 1px, 1px, 1px);padding:1px 0 0 0;border:0}.cherry-markdown.head-num{counter-reset:level1}.cherry-markdown.head-num h1 .anchor:before,.cherry-markdown.head-num h2 .anchor:before,.cherry-markdown.head-num h3 .anchor:before,.cherry-markdown.head-num h4 .anchor:before,.cherry-markdown.head-num h5 .anchor:before,.cherry-markdown.head-num h6 .anchor:before{width:auto;font-size:inherit;vertical-align:inherit;padding-right:10px}.cherry-markdown.head-num h1{counter-reset:level2}.cherry-markdown.head-num h2{counter-reset:level3}.cherry-markdown.head-num h3{counter-reset:level4}.cherry-markdown.head-num h4{counter-reset:level5}.cherry-markdown.head-num h5{counter-reset:level6}.cherry-markdown.head-num h1 .anchor:before{counter-increment:level1;content:counter(level1) ". "}.cherry-markdown.head-num h2 .anchor:before{counter-increment:level2;content:counter(level1) "." counter(level2) " "}.cherry-markdown.head-num h3 .anchor:before{counter-increment:level3;content:counter(level1) "." counter(level2) "." counter(level3) " "}.cherry-markdown.head-num h4 .anchor:before{counter-increment:level4;content:counter(level1) "." counter(level2) "." counter(level3) "." counter(level4) " "}.cherry-markdown.head-num h5 .anchor:before{counter-increment:level5;content:counter(level1) "." counter(level2) "." counter(level3) "." counter(level4) "." counter(level5) " "}.cherry-markdown.head-num h6 .anchor:before{counter-increment:level6;content:counter(level1) "." counter(level2) "." counter(level3) "." counter(level4) "." counter(level5) "." counter(level6) " "}div[data-type=codeBlock] code[class*=language-],div[data-type=codeBlock] pre[class*=language-]{color:#ccc;background:none;font-family:Consolas,Monaco,"Andale Mono","Ubuntu Mono",monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}div[data-type=codeBlock] pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}div[data-type=codeBlock] :not(pre)>code[class*=language-],div[data-type=codeBlock] pre[class*=language-]{background:#2d2d2d}div[data-type=codeBlock] :not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}div[data-type=codeBlock] .token.comment,div[data-type=codeBlock] .token.block-comment,div[data-type=codeBlock] .token.prolog,div[data-type=codeBlock] .token.doctype,div[data-type=codeBlock] .token.cdata{color:#999}div[data-type=codeBlock] .token.punctuation{color:#ccc}div[data-type=codeBlock] .token.tag,div[data-type=codeBlock] .token.attr-name,div[data-type=codeBlock] .token.namespace,div[data-type=codeBlock] .token.deleted{color:#e2777a}div[data-type=codeBlock] .token.function-name{color:#6196cc}div[data-type=codeBlock] .token.boolean,div[data-type=codeBlock] .token.number,div[data-type=codeBlock] .token.function{color:#f08d49}div[data-type=codeBlock] .token.property,div[data-type=codeBlock] .token.class-name,div[data-type=codeBlock] .token.constant,div[data-type=codeBlock] .token.symbol{color:#f8c555}div[data-type=codeBlock] .token.selector,div[data-type=codeBlock] .token.important,div[data-type=codeBlock] .token.atrule,div[data-type=codeBlock] .token.keyword,div[data-type=codeBlock] .token.builtin{color:#cc99cd}div[data-type=codeBlock] .token.string,div[data-type=codeBlock] .token.char,div[data-type=codeBlock] .token.attr-value,div[data-type=codeBlock] .token.regex,div[data-type=codeBlock] .token.variable{color:#7ec699}div[data-type=codeBlock] .token.operator,div[data-type=codeBlock] .token.entity,div[data-type=codeBlock] .token.url{color:#67cdcc}div[data-type=codeBlock] .token.important,div[data-type=codeBlock] .token.bold{font-weight:bold}div[data-type=codeBlock] .token.italic{font-style:italic}div[data-type=codeBlock] .token.entity{cursor:help}div[data-type=codeBlock] .token.inserted{color:green}[data-code-block-theme=default] div[data-type=codeBlock] code[class*=language-],[data-code-block-theme=default] div[data-type=codeBlock] pre[class*=language-]{color:#000;background:none;text-shadow:0 1px #fff;font-family:Consolas,Monaco,"Andale Mono","Ubuntu Mono",monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}[data-code-block-theme=default] div[data-type=codeBlock] pre[class*=language-]::-moz-selection,[data-code-block-theme=default] div[data-type=codeBlock] pre[class*=language-] ::-moz-selection,[data-code-block-theme=default] div[data-type=codeBlock] code[class*=language-]::-moz-selection,[data-code-block-theme=default] div[data-type=codeBlock] code[class*=language-] ::-moz-selection{text-shadow:none;background:#b3d4fc}[data-code-block-theme=default] div[data-type=codeBlock] pre[class*=language-]::selection,[data-code-block-theme=default] div[data-type=codeBlock] pre[class*=language-] ::selection,[data-code-block-theme=default] div[data-type=codeBlock] code[class*=language-]::selection,[data-code-block-theme=default] div[data-type=codeBlock] code[class*=language-] ::selection{text-shadow:none;background:#b3d4fc}@media print{[data-code-block-theme=default] div[data-type=codeBlock] code[class*=language-],[data-code-block-theme=default] div[data-type=codeBlock] pre[class*=language-]{text-shadow:none}}[data-code-block-theme=default] div[data-type=codeBlock] pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}[data-code-block-theme=default] div[data-type=codeBlock] :not(pre)>code[class*=language-],[data-code-block-theme=default] div[data-type=codeBlock] pre[class*=language-]{background:#f5f2f0}[data-code-block-theme=default] div[data-type=codeBlock] :not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}[data-code-block-theme=default] div[data-type=codeBlock] .token.comment,[data-code-block-theme=default] div[data-type=codeBlock] .token.prolog,[data-code-block-theme=default] div[data-type=codeBlock] .token.doctype,[data-code-block-theme=default] div[data-type=codeBlock] .token.cdata{color:#708090}[data-code-block-theme=default] div[data-type=codeBlock] .token.punctuation{color:#999}[data-code-block-theme=default] div[data-type=codeBlock] .token.namespace{opacity:.7}[data-code-block-theme=default] div[data-type=codeBlock] .token.property,[data-code-block-theme=default] div[data-type=codeBlock] .token.tag,[data-code-block-theme=default] div[data-type=codeBlock] .token.boolean,[data-code-block-theme=default] div[data-type=codeBlock] .token.number,[data-code-block-theme=default] div[data-type=codeBlock] .token.constant,[data-code-block-theme=default] div[data-type=codeBlock] .token.symbol,[data-code-block-theme=default] div[data-type=codeBlock] .token.deleted{color:#905}[data-code-block-theme=default] div[data-type=codeBlock] .token.selector,[data-code-block-theme=default] div[data-type=codeBlock] .token.attr-name,[data-code-block-theme=default] div[data-type=codeBlock] .token.string,[data-code-block-theme=default] div[data-type=codeBlock] .token.char,[data-code-block-theme=default] div[data-type=codeBlock] .token.builtin,[data-code-block-theme=default] div[data-type=codeBlock] .token.inserted{color:#690}[data-code-block-theme=default] div[data-type=codeBlock] .token.operator,[data-code-block-theme=default] div[data-type=codeBlock] .token.entity,[data-code-block-theme=default] div[data-type=codeBlock] .token.url,[data-code-block-theme=default] div[data-type=codeBlock] .language-css .token.string,[data-code-block-theme=default] div[data-type=codeBlock] .style .token.string{color:#9a6e3a;background:rgba(255,255,255,.5)}[data-code-block-theme=default] div[data-type=codeBlock] .token.atrule,[data-code-block-theme=default] div[data-type=codeBlock] .token.attr-value,[data-code-block-theme=default] div[data-type=codeBlock] .token.keyword{color:#07a}[data-code-block-theme=default] div[data-type=codeBlock] .token.function,[data-code-block-theme=default] div[data-type=codeBlock] .token.class-name{color:#dd4a68}[data-code-block-theme=default] div[data-type=codeBlock] .token.regex,[data-code-block-theme=default] div[data-type=codeBlock] .token.important,[data-code-block-theme=default] div[data-type=codeBlock] .token.variable{color:#e90}[data-code-block-theme=default] div[data-type=codeBlock] .token.important,[data-code-block-theme=default] div[data-type=codeBlock] .token.bold{font-weight:bold}[data-code-block-theme=default] div[data-type=codeBlock] .token.italic{font-style:italic}[data-code-block-theme=default] div[data-type=codeBlock] .token.entity{cursor:help}[data-code-block-theme=dark] div[data-type=codeBlock] code[class*=language-],[data-code-block-theme=dark] div[data-type=codeBlock] pre[class*=language-]{color:#fff;background:none;text-shadow:0 -0.1em .2em #000;font-family:Consolas,Monaco,"Andale Mono","Ubuntu Mono",monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}@media print{[data-code-block-theme=dark] div[data-type=codeBlock] code[class*=language-],[data-code-block-theme=dark] div[data-type=codeBlock] pre[class*=language-]{text-shadow:none}}[data-code-block-theme=dark] div[data-type=codeBlock] pre[class*=language-],[data-code-block-theme=dark] div[data-type=codeBlock] :not(pre)>code[class*=language-]{background:#4d4033}[data-code-block-theme=dark] div[data-type=codeBlock] pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;border:.3em solid #7a6652;border-radius:.5em;box-shadow:1px 1px .5em #000 inset}[data-code-block-theme=dark] div[data-type=codeBlock] :not(pre)>code[class*=language-]{padding:.15em .2em .05em;border-radius:.3em;border:.13em solid #7a6652;box-shadow:1px 1px .3em -0.1em #000 inset;white-space:normal}[data-code-block-theme=dark] div[data-type=codeBlock] .token.comment,[data-code-block-theme=dark] div[data-type=codeBlock] .token.prolog,[data-code-block-theme=dark] div[data-type=codeBlock] .token.doctype,[data-code-block-theme=dark] div[data-type=codeBlock] .token.cdata{color:#998066}[data-code-block-theme=dark] div[data-type=codeBlock] .token.punctuation{opacity:.7}[data-code-block-theme=dark] div[data-type=codeBlock] .token.namespace{opacity:.7}[data-code-block-theme=dark] div[data-type=codeBlock] .token.property,[data-code-block-theme=dark] div[data-type=codeBlock] .token.tag,[data-code-block-theme=dark] div[data-type=codeBlock] .token.boolean,[data-code-block-theme=dark] div[data-type=codeBlock] .token.number,[data-code-block-theme=dark] div[data-type=codeBlock] .token.constant,[data-code-block-theme=dark] div[data-type=codeBlock] .token.symbol{color:#d1949e}[data-code-block-theme=dark] div[data-type=codeBlock] .token.selector,[data-code-block-theme=dark] div[data-type=codeBlock] .token.attr-name,[data-code-block-theme=dark] div[data-type=codeBlock] .token.string,[data-code-block-theme=dark] div[data-type=codeBlock] .token.char,[data-code-block-theme=dark] div[data-type=codeBlock] .token.builtin,[data-code-block-theme=dark] div[data-type=codeBlock] .token.inserted{color:#bde052}[data-code-block-theme=dark] div[data-type=codeBlock] .token.operator,[data-code-block-theme=dark] div[data-type=codeBlock] .token.entity,[data-code-block-theme=dark] div[data-type=codeBlock] .token.url,[data-code-block-theme=dark] div[data-type=codeBlock] .language-css .token.string,[data-code-block-theme=dark] div[data-type=codeBlock] .style .token.string,[data-code-block-theme=dark] div[data-type=codeBlock] .token.variable{color:#f5b83d}[data-code-block-theme=dark] div[data-type=codeBlock] .token.atrule,[data-code-block-theme=dark] div[data-type=codeBlock] .token.attr-value,[data-code-block-theme=dark] div[data-type=codeBlock] .token.keyword{color:#d1949e}[data-code-block-theme=dark] div[data-type=codeBlock] .token.regex,[data-code-block-theme=dark] div[data-type=codeBlock] .token.important{color:#e90}[data-code-block-theme=dark] div[data-type=codeBlock] .token.important,[data-code-block-theme=dark] div[data-type=codeBlock] .token.bold{font-weight:bold}[data-code-block-theme=dark] div[data-type=codeBlock] .token.italic{font-style:italic}[data-code-block-theme=dark] div[data-type=codeBlock] .token.entity{cursor:help}[data-code-block-theme=dark] div[data-type=codeBlock] .token.deleted{color:red}[data-code-block-theme=funky] div[data-type=codeBlock] code[class*=language-],[data-code-block-theme=funky] div[data-type=codeBlock] pre[class*=language-]{font-family:Consolas,Monaco,"Andale Mono","Ubuntu Mono",monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}[data-code-block-theme=funky] div[data-type=codeBlock] pre[class*=language-]{padding:.4em .8em;margin:.5em 0;overflow:auto;background:url('data:image/svg+xml;charset=utf-8,%0D%0A%0D%0A%0D%0A<%2Fsvg>');background-size:1em 1em}[data-code-block-theme=funky] div[data-type=codeBlock] code[class*=language-]{background:#000;color:#fff;box-shadow:-0.3em 0 0 .3em #000,.3em 0 0 .3em #000}[data-code-block-theme=funky] div[data-type=codeBlock] :not(pre)>code[class*=language-]{padding:.2em;border-radius:.3em;box-shadow:none;white-space:normal}[data-code-block-theme=funky] div[data-type=codeBlock] .token.comment,[data-code-block-theme=funky] div[data-type=codeBlock] .token.prolog,[data-code-block-theme=funky] div[data-type=codeBlock] .token.doctype,[data-code-block-theme=funky] div[data-type=codeBlock] .token.cdata{color:#aaa}[data-code-block-theme=funky] div[data-type=codeBlock] .token.punctuation{color:#999}[data-code-block-theme=funky] div[data-type=codeBlock] .token.namespace{opacity:.7}[data-code-block-theme=funky] div[data-type=codeBlock] .token.property,[data-code-block-theme=funky] div[data-type=codeBlock] .token.tag,[data-code-block-theme=funky] div[data-type=codeBlock] .token.boolean,[data-code-block-theme=funky] div[data-type=codeBlock] .token.number,[data-code-block-theme=funky] div[data-type=codeBlock] .token.constant,[data-code-block-theme=funky] div[data-type=codeBlock] .token.symbol{color:#0cf}[data-code-block-theme=funky] div[data-type=codeBlock] .token.selector,[data-code-block-theme=funky] div[data-type=codeBlock] .token.attr-name,[data-code-block-theme=funky] div[data-type=codeBlock] .token.string,[data-code-block-theme=funky] div[data-type=codeBlock] .token.char,[data-code-block-theme=funky] div[data-type=codeBlock] .token.builtin{color:#ff0}[data-code-block-theme=funky] div[data-type=codeBlock] .token.operator,[data-code-block-theme=funky] div[data-type=codeBlock] .token.entity,[data-code-block-theme=funky] div[data-type=codeBlock] .token.url,[data-code-block-theme=funky] div[data-type=codeBlock] .language-css .token.string,[data-code-block-theme=funky] div[data-type=codeBlock] .token.variable,[data-code-block-theme=funky] div[data-type=codeBlock] .token.inserted{color:#9acd32}[data-code-block-theme=funky] div[data-type=codeBlock] .token.atrule,[data-code-block-theme=funky] div[data-type=codeBlock] .token.attr-value,[data-code-block-theme=funky] div[data-type=codeBlock] .token.keyword{color:#ff1493}[data-code-block-theme=funky] div[data-type=codeBlock] .token.regex,[data-code-block-theme=funky] div[data-type=codeBlock] .token.important{color:orange}[data-code-block-theme=funky] div[data-type=codeBlock] .token.important,[data-code-block-theme=funky] div[data-type=codeBlock] .token.bold{font-weight:bold}[data-code-block-theme=funky] div[data-type=codeBlock] .token.italic{font-style:italic}[data-code-block-theme=funky] div[data-type=codeBlock] .token.entity{cursor:help}[data-code-block-theme=funky] div[data-type=codeBlock] .token.deleted{color:red}[data-code-block-theme=funky] div[data-type=codeBlock] pre.diff-highlight.diff-highlight>code .token.deleted:not(.prefix),[data-code-block-theme=funky] div[data-type=codeBlock] pre>code.diff-highlight.diff-highlight .token.deleted:not(.prefix){background-color:rgba(255,0,0,.3);display:inline}[data-code-block-theme=funky] div[data-type=codeBlock] pre.diff-highlight.diff-highlight>code .token.inserted:not(.prefix),[data-code-block-theme=funky] div[data-type=codeBlock] pre>code.diff-highlight.diff-highlight .token.inserted:not(.prefix){background-color:rgba(0,255,128,.3);display:inline}[data-code-block-theme=okaidia] div[data-type=codeBlock] code[class*=language-],[data-code-block-theme=okaidia] div[data-type=codeBlock] pre[class*=language-]{color:#f8f8f2;background:none;text-shadow:0 1px rgba(0,0,0,.3);font-family:Consolas,Monaco,"Andale Mono","Ubuntu Mono",monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}[data-code-block-theme=okaidia] div[data-type=codeBlock] pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;border-radius:.3em}[data-code-block-theme=okaidia] div[data-type=codeBlock] :not(pre)>code[class*=language-],[data-code-block-theme=okaidia] div[data-type=codeBlock] pre[class*=language-]{background:#272822}[data-code-block-theme=okaidia] div[data-type=codeBlock] :not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.comment,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.prolog,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.doctype,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.cdata{color:#8292a2}[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.punctuation{color:#f8f8f2}[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.namespace{opacity:.7}[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.property,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.tag,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.constant,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.symbol,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.deleted{color:#f92672}[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.boolean,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.number{color:#ae81ff}[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.selector,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.attr-name,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.string,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.char,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.builtin,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.inserted{color:#a6e22e}[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.operator,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.entity,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.url,[data-code-block-theme=okaidia] div[data-type=codeBlock] .language-css .token.string,[data-code-block-theme=okaidia] div[data-type=codeBlock] .style .token.string,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.variable{color:#f8f8f2}[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.atrule,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.attr-value,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.function,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.class-name{color:#e6db74}[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.keyword{color:#66d9ef}[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.regex,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.important{color:#fd971f}[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.important,[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.bold{font-weight:bold}[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.italic{font-style:italic}[data-code-block-theme=okaidia] div[data-type=codeBlock] .token.entity{cursor:help}[data-code-block-theme=twilight] div[data-type=codeBlock] code[class*=language-],[data-code-block-theme=twilight] div[data-type=codeBlock] pre[class*=language-]{color:#fff;background:none;font-family:Consolas,Monaco,"Andale Mono","Ubuntu Mono",monospace;font-size:1em;text-align:left;text-shadow:0 -0.1em .2em #000;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}[data-code-block-theme=twilight] div[data-type=codeBlock] pre[class*=language-],[data-code-block-theme=twilight] div[data-type=codeBlock] :not(pre)>code[class*=language-]{background:#141414}[data-code-block-theme=twilight] div[data-type=codeBlock] pre[class*=language-]{border-radius:.5em;border:.3em solid #545454;box-shadow:1px 1px .5em #000 inset;margin:.5em 0;overflow:auto;padding:1em}[data-code-block-theme=twilight] div[data-type=codeBlock] pre[class*=language-]::-moz-selection{background:#27292a}[data-code-block-theme=twilight] div[data-type=codeBlock] pre[class*=language-]::selection{background:#27292a}[data-code-block-theme=twilight] div[data-type=codeBlock] pre[class*=language-]::-moz-selection,[data-code-block-theme=twilight] div[data-type=codeBlock] pre[class*=language-] ::-moz-selection,[data-code-block-theme=twilight] div[data-type=codeBlock] code[class*=language-]::-moz-selection,[data-code-block-theme=twilight] div[data-type=codeBlock] code[class*=language-] ::-moz-selection{text-shadow:none;background:rgba(237,237,237,.15)}[data-code-block-theme=twilight] div[data-type=codeBlock] pre[class*=language-]::selection,[data-code-block-theme=twilight] div[data-type=codeBlock] pre[class*=language-] ::selection,[data-code-block-theme=twilight] div[data-type=codeBlock] code[class*=language-]::selection,[data-code-block-theme=twilight] div[data-type=codeBlock] code[class*=language-] ::selection{text-shadow:none;background:rgba(237,237,237,.15)}[data-code-block-theme=twilight] div[data-type=codeBlock] :not(pre)>code[class*=language-]{border-radius:.3em;border:.13em solid #545454;box-shadow:1px 1px .3em -0.1em #000 inset;padding:.15em .2em .05em;white-space:normal}[data-code-block-theme=twilight] div[data-type=codeBlock] .token.comment,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.prolog,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.doctype,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.cdata{color:#787878}[data-code-block-theme=twilight] div[data-type=codeBlock] .token.punctuation{opacity:.7}[data-code-block-theme=twilight] div[data-type=codeBlock] .token.namespace{opacity:.7}[data-code-block-theme=twilight] div[data-type=codeBlock] .token.tag,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.boolean,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.number,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.deleted{color:#cf694a}[data-code-block-theme=twilight] div[data-type=codeBlock] .token.keyword,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.property,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.selector,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.constant,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.symbol,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.builtin{color:#f9ee9a}[data-code-block-theme=twilight] div[data-type=codeBlock] .token.attr-name,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.attr-value,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.string,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.char,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.operator,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.entity,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.url,[data-code-block-theme=twilight] div[data-type=codeBlock] .language-css .token.string,[data-code-block-theme=twilight] div[data-type=codeBlock] .style .token.string,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.variable,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.inserted{color:#919e6b}[data-code-block-theme=twilight] div[data-type=codeBlock] .token.atrule{color:#7386a5}[data-code-block-theme=twilight] div[data-type=codeBlock] .token.regex,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.important{color:#e9c163}[data-code-block-theme=twilight] div[data-type=codeBlock] .token.important,[data-code-block-theme=twilight] div[data-type=codeBlock] .token.bold{font-weight:bold}[data-code-block-theme=twilight] div[data-type=codeBlock] .token.italic{font-style:italic}[data-code-block-theme=twilight] div[data-type=codeBlock] .token.entity{cursor:help}[data-code-block-theme=twilight] div[data-type=codeBlock] pre[data-line]{padding:1em 0 1em 3em;position:relative}[data-code-block-theme=twilight] div[data-type=codeBlock] .language-markup .token.tag,[data-code-block-theme=twilight] div[data-type=codeBlock] .language-markup .token.attr-name,[data-code-block-theme=twilight] div[data-type=codeBlock] .language-markup .token.punctuation{color:#ad895c}[data-code-block-theme=twilight] div[data-type=codeBlock] .token{position:relative;z-index:1}[data-code-block-theme=twilight] div[data-type=codeBlock] .line-highlight{background:rgba(84,84,84,.25);background:linear-gradient(to right, hsla(0deg, 0%, 33%, 0.1) 70%, hsla(0deg, 0%, 33%, 0));border-bottom:1px dashed #545454;border-top:1px dashed #545454;left:0;line-height:inherit;margin-top:.75em;padding:inherit 0;pointer-events:none;position:absolute;right:0;white-space:pre;z-index:0}[data-code-block-theme=twilight] div[data-type=codeBlock] .line-highlight:before,[data-code-block-theme=twilight] div[data-type=codeBlock] .line-highlight[data-end]:after{background-color:#8794a6;border-radius:999px;box-shadow:0 1px #fff;color:#f5f2f0;content:attr(data-start);font:bold 65%/1.5 sans-serif;left:.6em;min-width:1em;padding:0 .5em;position:absolute;text-align:center;text-shadow:none;top:.4em;vertical-align:.3em}[data-code-block-theme=twilight] div[data-type=codeBlock] .line-highlight[data-end]:after{bottom:.4em;content:attr(data-end);top:auto}[data-code-block-theme=coy] div[data-type=codeBlock] code[class*=language-],[data-code-block-theme=coy] div[data-type=codeBlock] pre[class*=language-]{color:#000;background:none;font-family:Consolas,Monaco,"Andale Mono","Ubuntu Mono",monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}[data-code-block-theme=coy] div[data-type=codeBlock] pre[class*=language-]{position:relative;margin:.5em 0;overflow-y:hidden;padding:0}[data-code-block-theme=coy] div[data-type=codeBlock] pre[class*=language-]>code{position:relative;border-left:10px solid #358ccb;box-shadow:-1px 0px 0px 0px #358ccb,0px 0px 0px 1px #dfdfdf;background-color:#fdfdfd;background-image:linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%);background-size:3em 3em;background-origin:content-box;background-attachment:local}[data-code-block-theme=coy] div[data-type=codeBlock] code[class*=language-]{max-height:inherit;height:inherit;padding:0 1em;display:block}[data-code-block-theme=coy] div[data-type=codeBlock] :not(pre)>code[class*=language-],[data-code-block-theme=coy] div[data-type=codeBlock] pre[class*=language-]{background-color:#fdfdfd;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin-bottom:1em}[data-code-block-theme=coy] div[data-type=codeBlock] :not(pre)>code[class*=language-]{position:relative;padding:.2em;border-radius:.3em;color:#c92c2c;border:1px solid rgba(0,0,0,.1);display:inline;white-space:normal}[data-code-block-theme=coy] div[data-type=codeBlock] pre[class*=language-]:before,[data-code-block-theme=coy] div[data-type=codeBlock] pre[class*=language-]:after{content:"";z-index:-2;display:block;position:absolute;bottom:.75em;left:.18em;width:40%;height:20%;max-height:13em;box-shadow:0px 13px 8px #979797;-webkit-transform:rotate(-2deg);-moz-transform:rotate(-2deg);-ms-transform:rotate(-2deg);-o-transform:rotate(-2deg);transform:rotate(-2deg)}[data-code-block-theme=coy] div[data-type=codeBlock] pre[class*=language-]:after{right:.75em;left:auto;-webkit-transform:rotate(2deg);-moz-transform:rotate(2deg);-ms-transform:rotate(2deg);-o-transform:rotate(2deg);transform:rotate(2deg)}[data-code-block-theme=coy] div[data-type=codeBlock] .token.comment,[data-code-block-theme=coy] div[data-type=codeBlock] .token.block-comment,[data-code-block-theme=coy] div[data-type=codeBlock] .token.prolog,[data-code-block-theme=coy] div[data-type=codeBlock] .token.doctype,[data-code-block-theme=coy] div[data-type=codeBlock] .token.cdata{color:#7d8b99}[data-code-block-theme=coy] div[data-type=codeBlock] .token.punctuation{color:#5f6364}[data-code-block-theme=coy] div[data-type=codeBlock] .token.property,[data-code-block-theme=coy] div[data-type=codeBlock] .token.tag,[data-code-block-theme=coy] div[data-type=codeBlock] .token.boolean,[data-code-block-theme=coy] div[data-type=codeBlock] .token.number,[data-code-block-theme=coy] div[data-type=codeBlock] .token.function-name,[data-code-block-theme=coy] div[data-type=codeBlock] .token.constant,[data-code-block-theme=coy] div[data-type=codeBlock] .token.symbol,[data-code-block-theme=coy] div[data-type=codeBlock] .token.deleted{color:#c92c2c}[data-code-block-theme=coy] div[data-type=codeBlock] .token.selector,[data-code-block-theme=coy] div[data-type=codeBlock] .token.attr-name,[data-code-block-theme=coy] div[data-type=codeBlock] .token.string,[data-code-block-theme=coy] div[data-type=codeBlock] .token.char,[data-code-block-theme=coy] div[data-type=codeBlock] .token.function,[data-code-block-theme=coy] div[data-type=codeBlock] .token.builtin,[data-code-block-theme=coy] div[data-type=codeBlock] .token.inserted{color:#2f9c0a}[data-code-block-theme=coy] div[data-type=codeBlock] .token.operator,[data-code-block-theme=coy] div[data-type=codeBlock] .token.entity,[data-code-block-theme=coy] div[data-type=codeBlock] .token.url,[data-code-block-theme=coy] div[data-type=codeBlock] .token.variable{color:#a67f59;background:rgba(255,255,255,.5)}[data-code-block-theme=coy] div[data-type=codeBlock] .token.atrule,[data-code-block-theme=coy] div[data-type=codeBlock] .token.attr-value,[data-code-block-theme=coy] div[data-type=codeBlock] .token.keyword,[data-code-block-theme=coy] div[data-type=codeBlock] .token.class-name{color:#1990b8}[data-code-block-theme=coy] div[data-type=codeBlock] .token.regex,[data-code-block-theme=coy] div[data-type=codeBlock] .token.important{color:#e90}[data-code-block-theme=coy] div[data-type=codeBlock] .language-css .token.string,[data-code-block-theme=coy] div[data-type=codeBlock] .style .token.string{color:#a67f59;background:rgba(255,255,255,.5)}[data-code-block-theme=coy] div[data-type=codeBlock] .token.important{font-weight:normal}[data-code-block-theme=coy] div[data-type=codeBlock] .token.bold{font-weight:bold}[data-code-block-theme=coy] div[data-type=codeBlock] .token.italic{font-style:italic}[data-code-block-theme=coy] div[data-type=codeBlock] .token.entity{cursor:help}[data-code-block-theme=coy] div[data-type=codeBlock] .token.namespace{opacity:.7}@media screen and (max-width: 767px){[data-code-block-theme=coy] div[data-type=codeBlock] pre[class*=language-]:before,[data-code-block-theme=coy] div[data-type=codeBlock] pre[class*=language-]:after{bottom:14px;box-shadow:none}}[data-code-block-theme=coy] div[data-type=codeBlock] pre[class*=language-].line-numbers.line-numbers{padding-left:0}[data-code-block-theme=coy] div[data-type=codeBlock] pre[class*=language-].line-numbers.line-numbers code{padding-left:3.8em}[data-code-block-theme=coy] div[data-type=codeBlock] pre[class*=language-].line-numbers.line-numbers .line-numbers-rows{left:0}[data-code-block-theme=coy] div[data-type=codeBlock] pre[class*=language-][data-line]{padding-top:0;padding-bottom:0;padding-left:0}[data-code-block-theme=coy] div[data-type=codeBlock] pre[data-line] code{position:relative;padding-left:4em}[data-code-block-theme=coy] div[data-type=codeBlock] pre .line-highlight{margin-top:0}[data-code-block-theme=solarized-light] div[data-type=codeBlock] code[class*=language-],[data-code-block-theme=solarized-light] div[data-type=codeBlock] pre[class*=language-]{color:#657b83;font-family:Consolas,Monaco,"Andale Mono","Ubuntu Mono",monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}[data-code-block-theme=solarized-light] div[data-type=codeBlock] pre[class*=language-]::-moz-selection,[data-code-block-theme=solarized-light] div[data-type=codeBlock] pre[class*=language-] ::-moz-selection,[data-code-block-theme=solarized-light] div[data-type=codeBlock] code[class*=language-]::-moz-selection,[data-code-block-theme=solarized-light] div[data-type=codeBlock] code[class*=language-] ::-moz-selection{background:#073642}[data-code-block-theme=solarized-light] div[data-type=codeBlock] pre[class*=language-]::selection,[data-code-block-theme=solarized-light] div[data-type=codeBlock] pre[class*=language-] ::selection,[data-code-block-theme=solarized-light] div[data-type=codeBlock] code[class*=language-]::selection,[data-code-block-theme=solarized-light] div[data-type=codeBlock] code[class*=language-] ::selection{background:#073642}[data-code-block-theme=solarized-light] div[data-type=codeBlock] pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto;border-radius:.3em}[data-code-block-theme=solarized-light] div[data-type=codeBlock] :not(pre)>code[class*=language-],[data-code-block-theme=solarized-light] div[data-type=codeBlock] pre[class*=language-]{background-color:#fdf6e3}[data-code-block-theme=solarized-light] div[data-type=codeBlock] :not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em}[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.comment,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.prolog,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.doctype,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.cdata{color:#93a1a1}[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.punctuation{color:#586e75}[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.namespace{opacity:.7}[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.property,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.tag,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.boolean,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.number,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.constant,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.symbol,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.deleted{color:#268bd2}[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.selector,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.attr-name,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.string,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.char,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.builtin,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.url,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.inserted{color:#2aa198}[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.entity{color:#657b83;background:#eee8d5}[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.atrule,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.attr-value,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.keyword{color:#859900}[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.function,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.class-name{color:#b58900}[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.regex,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.important,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.variable{color:#cb4b16}[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.important,[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.bold{font-weight:bold}[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.italic{font-style:italic}[data-code-block-theme=solarized-light] div[data-type=codeBlock] .token.entity{cursor:help}.cherry .doing-resize-img{-moz-user-select:none;-webkit-user-select:none;user-select:none}.cherry .cherry-previewer img{transition:all .1s}.cherry .cherry-previewer-img-size-hander{position:absolute;box-shadow:0 1px 4px 0 rgba(20,81,154,.5);border:1px solid #3582fb;box-sizing:content-box;pointer-events:none}.cherry .cherry-previewer-img-size-hander .cherry-previewer-img-size-hander__points{position:absolute;height:10px;width:10px;margin-top:-7px;margin-left:-7px;border-radius:9px;background:#3582fb;border:2px solid #fff;box-sizing:content-box;box-shadow:0px 2px 2px 0px rgba(20,81,154,.5);pointer-events:all}.cherry .cherry-previewer-img-size-hander .cherry-previewer-img-size-hander__background{background-repeat:no-repeat;background-size:100% 100%;opacity:.5;width:100%;height:100%}.cherry .cherry-previewer-img-size-hander .cherry-previewer-img-size-hander__points-leftTop{cursor:nw-resize}.cherry .cherry-previewer-img-size-hander .cherry-previewer-img-size-hander__points-rightTop{cursor:sw-resize}.cherry .cherry-previewer-img-size-hander .cherry-previewer-img-size-hander__points-leftBottom{cursor:sw-resize}.cherry .cherry-previewer-img-size-hander .cherry-previewer-img-size-hander__points-rightBottom{cursor:nw-resize}.cherry .cherry-previewer-img-size-hander .cherry-previewer-img-size-hander__points-middleTop{cursor:n-resize}.cherry .cherry-previewer-img-size-hander .cherry-previewer-img-size-hander__points-middleBottom{cursor:n-resize}.cherry .cherry-previewer-img-size-hander .cherry-previewer-img-size-hander__points-leftMiddle{cursor:e-resize}.cherry .cherry-previewer-img-size-hander .cherry-previewer-img-size-hander__points-rightMiddle{cursor:e-resize}.cherry .cherry-previewer-table-content-hander .cherry-previewer-table-content-hander__input{position:absolute}.cherry .cherry-previewer-table-content-hander .cherry-previewer-table-content-hander__input textarea{width:100%;height:100%;border:0;box-sizing:border-box;resize:none;outline:1px solid #3582fb;word-break:break-all}@media print{img,figure,pre,table{page-break-inside:avoid}.cherry-previewer{width:100% !important;max-height:none;border-left:none !important}.cherry-toolbar,.cherry-sidebar,.cherry-editor,.cherry-drag{display:none !important}}.cherry{display:flex;flex-flow:row wrap;align-items:stretch;align-content:flex-start;height:100%;min-height:100px;position:relative}.cherry .cherry-editor,.cherry .cherry-previewer{max-height:calc(100% - 48px);min-height:calc(100% - 48px)}.cherry .CodeMirror{height:100%}.cherry.cherry--no-toolbar .cherry-toolbar,.cherry.cherry--no-toolbar .cherry-sidebar{height:0;display:none}.cherry.cherry--no-toolbar .cherry-editor,.cherry.cherry--no-toolbar .cherry-previewer{max-height:100%;min-height:100%}.cherry{font-family:"Helvetica Neue",Arial,"Hiragino Sans GB","STHeiti","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;font-size:16px;line-height:27px;color:#3f4a56;background:#f8fafb;box-shadow:0 0 10px rgba(128,145,165,.2)}.cherry .ch-icon{vertical-align:middle}.cherry .clearfix{zoom:1}.cherry .clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden;overflow:hidden;font-size:0}.cherry.fullscreen{position:fixed;top:0;left:0;right:0;bottom:0;z-index:1000}.cherry .no-select{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.cherry .cherry-insert-table-menu{display:block;position:fixed;top:40px;left:40px;border-collapse:separate;box-shadow:0 0 10px rgba(128,145,165,.2);padding:4px;border-radius:3px;width:auto;height:auto}.cherry .cherry-insert-table-menu-item{padding:7px;border:1px solid #dfe6ee}.cherry .cherry-insert-table-menu-item.active{background-color:#ebf3ff}.cherry[data-toolbar-theme=dark] .cherry-insert-table-menu-item{border-color:rgba(255,255,255,.2)}.cherry[data-toolbar-theme=dark] .cherry-insert-table-menu-item.active{background-color:#d7e6fe}.cherry-dropdown{position:absolute;width:130px;min-height:40px;background:#fff;box-shadow:0 5px 15px -5px rgba(0,0,0,.5);margin-left:-60px;z-index:8}.cherry-dropdown-item{width:100%;padding:0 15px;text-align:left;display:inline-block;height:36px;line-height:36px;font-size:14px;font-style:normal;cursor:pointer;box-sizing:border-box}.cherry-dropdown-item:hover{background:#ebf3ff;color:#5d9bfc}.cherry-dropdown-item .ch-icon{margin-right:10px}[data-toolbar-theme=dark] .cherry-dropdown{background:#20304b}[data-toolbar-theme=dark] .cherry-dropdown .cherry-dropdown-item{background:rgba(0,0,0,0);color:#d7e6fe}[data-toolbar-theme=dark] .cherry-dropdown .cherry-dropdown-item:hover{background:rgba(255,255,255,.1);color:#fff}.cherry-toolbar{position:relative;display:flex;align-items:center;padding:0 20px;height:48px;font-size:14px;line-height:2.8;flex-basis:100%;box-sizing:border-box;z-index:2;user-select:none;box-shadow:0 0 10px rgba(128,145,165,.2);background:#fff;overflow:hidden}[data-toolbar-theme=dark] .cherry-toolbar{background:#20304b;box-shadow:0 0 10px rgba(128,145,165,.2)}[data-toolbar-theme=dark] .cherry-toolbar .cherry-toolbar-button{color:#d7e6fe;background:rgba(0,0,0,0)}[data-toolbar-theme=dark] .cherry-toolbar .cherry-toolbar-button:hover{color:#fff;background:rgba(255,255,255,.1)}.cherry-toolbar.preview-only .cherry-toolbar-button{display:none}.cherry-toolbar.preview-only .cherry-toolbar-switchPreview{display:inline}.cherry-toolbar-button{float:left;padding:0 12px;height:38px;color:#3f4a56;background:rgba(0,0,0,0);border:1px solid rgba(0,0,0,0);-webkit-transition:background-color ease-in-out .15s,color ease-in-out .15s,border-color ease-in-out .15s;transition:background-color ease-in-out .15s,color ease-in-out .15s,border-color ease-in-out .15s;cursor:pointer;font-style:normal}.cherry-toolbar-button:hover{color:#5d9bfc;background:#ebf3ff}.cherry-toolbar-button.cherry-toolbar-split{font-size:0;height:50%;padding:0;margin-left:4px;margin-right:4px;border:none;border-left:1px solid #dfe6ee;pointer-events:none;overflow:hidden;opacity:.5}.cherry-toolbar-button.disabled{color:#ccc}.cherry .ace_search{background:#fff}.cherry-sidebar{width:30px;position:absolute;top:48px;right:7px;z-index:0;bottom:0;overflow:hidden}.cherry-sidebar .cherry-toolbar-button{height:30px;padding:3px 12px 0 6px}.cherry-sidebar .cherry-toolbar-button:hover{background:rgba(0,0,0,0)}.cherry-sidebar .cherry-toolbar-button .icon-loading.loading{display:inline-block;width:8px;height:8px}.cherry-sidebar .cherry-toolbar-button .icon-loading.loading:after{content:" ";display:block;width:8px;height:8px;margin-left:2px;margin-top:-2px;border-radius:50%;border:2px solid #000;border-color:#000 rgba(0,0,0,0) #000 rgba(0,0,0,0);animation:loading 1.2s linear infinite}@keyframes loading{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.cherry-bubble{position:absolute;display:flex;align-items:center;justify-content:flex-start;flex-wrap:wrap;font-size:14px;min-height:35px;min-width:50px;border:1px solid #dfe6ee;background-color:#fff;box-shadow:0 2px 15px -5px rgba(0,0,0,.5);border-radius:3px;z-index:8}.cherry-bubble.cherry-bubble--centered{left:50%;transform:translateX(-50%)}.cherry-bubble .cherry-bubble-top,.cherry-bubble .cherry-bubble-bottom{position:absolute;left:50%;width:0;height:0;margin-left:-8px;border-left:8px solid rgba(0,0,0,0);border-right:8px solid rgba(0,0,0,0)}.cherry-bubble .cherry-bubble-top{top:0;transform:translateY(-100%);border-bottom:8px solid #fff}.cherry-bubble .cherry-bubble-bottom{bottom:0;transform:translateY(100%);border-top:8px solid #fff}.cherry-bubble .cherry-toolbar-button{display:inline-flex;align-items:center;justify-content:center;height:35px;cursor:pointer;user-select:none}.cherry-bubble .cherry-toolbar-button:hover{border-color:#dfe6ee;background-color:rgba(89,128,166,.05)}.cherry-bubble .cherry-toolbar-button.cherry-toolbar-split{height:65%;min-height:22.75px}[data-toolbar-theme=dark] .cherry-bubble{border-color:#20304b;background:#20304b}[data-toolbar-theme=dark] .cherry-bubble .cherry-toolbar-button{color:#d7e6fe;background:rgba(0,0,0,0)}[data-toolbar-theme=dark] .cherry-bubble .cherry-toolbar-button:hover{color:#fff;background:rgba(255,255,255,.1)}[data-toolbar-theme=dark] .cherry-bubble .cherry-bubble-top{border-bottom-color:#20304b}[data-toolbar-theme=dark] .cherry-bubble .cherry-bubble-bottom{border-top-color:#20304b}[data-toolbar-theme=dark] .cherry-bubble .cherry-toolbar-button:hover{border-color:#20304b}.cherry-switch-paste .switch-btn--bg{position:absolute;width:50%;height:100%;box-sizing:border-box;z-index:-1;left:0;top:0;opacity:.3;background-color:#5d9bfc;border-radius:2px;transition:all .3s}.cherry-switch-paste .cherry-toolbar-button{display:inline-flex;align-items:center;justify-content:center;width:80px;text-align:center}.cherry-switch-paste .cherry-toolbar-button:hover{border-color:rgba(0,0,0,0)}.cherry-switch-paste[data-type=text] .cherry-text-btn{color:#3f4a56}.cherry-switch-paste[data-type=text] .cherry-md-btn{color:#5d9bfc}.cherry-switch-paste[data-type=md] .cherry-md-btn{color:#3f4a56}.cherry-switch-paste[data-type=md] .cherry-text-btn{color:#5d9bfc}.cherry-switch-paste[data-type=md] .switch-btn--bg{left:50%}[data-toolbar-theme=dark] .cherry-switch-paste .switch-btn--bg{background-color:#fff}[data-toolbar-theme=dark] .cherry-switch-paste[data-type=text] .cherry-text-btn{color:#d7e6fe}[data-toolbar-theme=dark] .cherry-switch-paste[data-type=text] .cherry-md-btn{color:#fff}[data-toolbar-theme=dark] .cherry-switch-paste[data-type=md] .cherry-md-btn{color:#d7e6fe}[data-toolbar-theme=dark] .cherry-switch-paste[data-type=md] .cherry-text-btn{color:#fff}[data-toolbar-theme=dark] .cherry-switch-paste[data-type=md] .switch-btn--bg{left:50%}.cherry-floatmenu{z-index:4;display:none;position:absolute;left:30px;margin-left:60px;height:27px;line-height:27px;border-radius:3px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.cherry-floatmenu .cherry-toolbar-button{float:left;padding:0 9px;margin:0;height:27px;line-height:27px;font-size:14px;color:#3f4a56;overflow:hidden;vertical-align:middle;text-align:center;border:0;cursor:pointer;font-style:normal}.cherry-floatmenu .cherry-toolbar-button.cherry-toolbar-split{border-left:1px solid #dfe6ee;width:0;padding:0;overflow:hidden;height:25px}.cherry-floatmenu .cherry-toolbar-button .ch-icon{color:#aaa;font-size:12px}.cherry-floatmenu .cherry-toolbar-button:hover{background:rgba(0,0,0,.05)}.cherry-floatmenu .cherry-toolbar-button:hover .ch-icon{color:#3f4a56}.cherry-editor{position:relative;padding-top:5px;padding-right:5px;width:50%;box-sizing:border-box;overflow:hidden}.cherry-editor.cherry-editor--full{width:100%;padding-right:0}.cherry-editor.cherry-editor--hidden{display:none}.cherry-editor .CodeMirror{font-family:"Helvetica Neue",Arial,"Hiragino Sans GB","STHeiti","Microsoft YaHei","WenQuanYi Micro Hei",sans-serif;background:#f8fafb;color:#3f4a56}.cherry-editor .CodeMirror textarea{font-size:27px}.cherry-editor .CodeMirror-lines{padding:15px 34px}.cherry-editor .cm-s-default .cm-header{color:#3f4a56}.cherry-editor .cm-s-default .cm-string{color:#3f4a56}.cherry-editor .cm-s-default .cm-comment{color:#3582fb;font-family:"Menlo","Liberation Mono","Consolas","DejaVu Sans Mono","Ubuntu Mono","Courier New","andale mono","lucida console",monospace;font-size:.9em}.cherry-editor .cm-s-default .cm-whitespace,.cherry-editor .cm-tab{font-family:"Menlo","Liberation Mono","Consolas","DejaVu Sans Mono","Ubuntu Mono","Courier New","andale mono","lucida console",monospace;font-size:.9em}.cherry-editor .cm-s-default .cm-quote{color:#3582fb}.cherry-editor .cm-s-default .cm-link{color:#3582fb}.cherry-editor .cm-s-default .cm-url{background:#d7e6fe;font-family:"Menlo","Liberation Mono","Consolas","DejaVu Sans Mono","Ubuntu Mono","Courier New","andale mono","lucida console",monospace;font-size:.9em}.cherry-editor .cm-s-default .cm-variable-2{color:#3f4a56}.cherry-editor .cm-s-default .cm-variable-3{color:#3f4a56}.cherry-editor .cm-s-default .cm-keyword{color:#3f4a56}.cherry-drag{width:15px;cursor:ew-resize;position:absolute;z-index:12;background:rgba(0,0,0,0)}.cherry-drag.cherry-drag--show{width:5px;display:block;background:#dfe6ee}.cherry-drag.cherry-drag--hidden{display:none}.cherry-editor-mask{z-index:10;position:absolute;display:none;background:rgba(0,0,0,.2)}.cherry-editor-mask.cherry-editor-mask--show{display:block}.cherry-previewer-mask{z-index:10;position:absolute;display:none;background:rgba(0,0,0,.4)}.cherry-previewer-mask.cherry-previewer-mask--show{display:block}.cherry-previewer{padding:20px 34px;border-left:2px solid #ebedee;width:50%;box-sizing:border-box;background-color:#f8fafb;min-height:auto;overflow-y:auto}.cherry-previewer .cherry-mobile-previewer-content{width:375px;height:100%;margin:0 auto;padding:25px 30px;overflow-y:scroll;box-shadow:0 0 60px rgba(0,0,0,.1);box-sizing:border-box}.cherry-previewer.cherry-previewer--hidden{width:0;display:none}.cherry-previewer.cherry-previewer--full{width:100%}.cherry-previewer .cherry-list__upper-roman{list-style:upper-roman}.cherry-previewer .cherry-list__lower-greek{list-style:lower-greek}.cherry-previewer .cherry-list__cjk-ideographic{list-style:cjk-ideographic}.cherry-previewer .cherry-list__circle{list-style:circle}.cherry-previewer .cherry-list__square{list-style:square}.cherry-previewer div[data-type=codeBlock]:hover .cherry-copy-code-block{display:block !important;position:relative;width:25px;text-align:center;height:25px;border:1px solid #ddd;cursor:pointer;float:right;right:10px;top:15px;color:#fff;border-radius:5px;margin-left:-27px;transition:all .3s;z-index:2}[data-code-block-theme=default] .cherry-previewer div[data-type=codeBlock]:hover .cherry-copy-code-block,[data-code-block-theme=funky] .cherry-previewer div[data-type=codeBlock]:hover .cherry-copy-code-block,[data-code-block-theme=solarized-light] .cherry-previewer div[data-type=codeBlock]:hover .cherry-copy-code-block,[data-code-block-theme=coy] .cherry-previewer div[data-type=codeBlock]:hover .cherry-copy-code-block{background-color:#3582fb}.cherry-previewer div[data-type=codeBlock]:hover .cherry-copy-code-block:hover{color:#3582fb;background-color:#eee;border-color:#3582fb}.cherry-color-wrap{display:none;position:fixed;width:auto;padding:5px 10px;z-index:6;background:#fff;box-shadow:0 0 10px rgba(128,145,165,.2)}.cherry-color-wrap h3{font-size:12px;margin:0px;font-weight:400}[data-toolbar-theme=dark] .cherry-color-wrap h3{color:#d7e6fe}.cherry-color-wrap .cherry-color-text{float:left;width:128px;margin:0 8px 0 5px}.cherry-color-wrap .cherry-color-bg{float:left;width:128px;margin-right:5px}.cherry-color-wrap .cherry-color-item{float:left;width:14px;height:14px;border:1px solid #fff;cursor:pointer}.cherry-color-wrap .cherry-color-item:hover{border:1px solid #000}.Cherry-Math svg{max-width:100%}.cherry-suggester-panel{display:none;position:absolute;left:0;top:0;background:#fff;border:1px solid #ccc;border-radius:2px;max-height:200px;box-shadow:0 2px 8px 1px rgba(0,0,0,.2)}.cherry-suggester-panel .cherry-suggester-panel__item{border:none;white-space:nowrap;min-width:50px;padding:5px 13px;color:#333;display:block;cursor:pointer}.cherry-suggester-panel .cherry-suggester-panel__item.cherry-suggester-panel__item--selected{background-color:#f2f2f5;text-decoration:none;color:#eb7350}.cherry-suggestion{background-color:#ebf3ff;color:#3582fb;padding:1px 4px;border-radius:3px;cursor:pointer}.cherry-markdown.theme__default ul.cherry-list__upper-roman{list-style:upper-roman}.cherry-markdown.theme__default ul.cherry-list__lower-greek{list-style:lower-greek}.cherry-markdown.theme__default ul.cherry-list__cjk-ideographic{list-style:cjk-ideographic}.cherry-markdown.theme__default ul.cherry-list__circle{list-style:circle}.cherry-markdown.theme__default ul.cherry-list__square{list-style:square}.cherry.theme__dark .cherry-toolbar,.cherry.theme__dark .cherry-floatmenu,.cherry.theme__dark .cherry-bubble,.cherry.theme__dark .cherry-sidebar{background:#3c3c3c;border-color:#3c3c3c}.cherry.theme__dark .cherry-toolbar .cherry-toolbar-button,.cherry.theme__dark .cherry-floatmenu .cherry-toolbar-button,.cherry.theme__dark .cherry-bubble .cherry-toolbar-button,.cherry.theme__dark .cherry-sidebar .cherry-toolbar-button{color:#d7e6fe}.cherry.theme__dark .cherry-toolbar .cherry-toolbar-button:hover,.cherry.theme__dark .cherry-floatmenu .cherry-toolbar-button:hover,.cherry.theme__dark .cherry-bubble .cherry-toolbar-button:hover,.cherry.theme__dark .cherry-sidebar .cherry-toolbar-button:hover{background-color:#454646;color:#fff !important;border-color:#3c3c3c}.cherry.theme__dark .cherry-toolbar .cherry-toolbar-button:hover i,.cherry.theme__dark .cherry-floatmenu .cherry-toolbar-button:hover i,.cherry.theme__dark .cherry-bubble .cherry-toolbar-button:hover i,.cherry.theme__dark .cherry-sidebar .cherry-toolbar-button:hover i{color:#fff !important}.cherry.theme__dark .cherry-dropdown{background:#3c3c3c}.cherry.theme__dark .cherry-dropdown .cherry-dropdown-item{color:#d7e6fe}.cherry.theme__dark .cherry-dropdown .cherry-dropdown-item:hover{background-color:#454646;color:#fff}.cherry.theme__dark .cherry-dropdown.cherry-color-wrap h3{color:#d7e6fe}.cherry.theme__dark .cherry-dropdown.cherry-color-wrap .cherry-color-item{border-color:#454646}.cherry.theme__dark .cherry-dropdown.cherry-color-wrap .cherry-color-item:hover{border-color:#f78553}.cherry.theme__dark .cherry-bubble .cherry-bubble-bottom{border-top-color:#3c3c3c}.cherry.theme__dark .cherry-editor{background-color:#252526}.cherry.theme__dark .cherry-editor .CodeMirror{background-color:#252526}.cherry.theme__dark .cherry-editor .CodeMirror .CodeMirror-cursor{border-left:1px solid #fff}.cherry.theme__dark .cherry-editor .CodeMirror .CodeMirror-scroll span,.cherry.theme__dark .cherry-editor .CodeMirror .CodeMirror-scroll .cm-variable-2,.cherry.theme__dark .cherry-editor .CodeMirror .CodeMirror-scroll .cm-string,.cherry.theme__dark .cherry-editor .CodeMirror .CodeMirror-scroll .cm-strong,.cherry.theme__dark .cherry-editor .CodeMirror .CodeMirror-scroll .cm-em,.cherry.theme__dark .cherry-editor .CodeMirror .CodeMirror-scroll .cm-meta{color:#c8c8c8}.cherry.theme__dark .cherry-editor .CodeMirror .CodeMirror-scroll .cm-image-marker,.cherry.theme__dark .cherry-editor .CodeMirror .CodeMirror-scroll .cm-quote,.cherry.theme__dark .cherry-editor .CodeMirror .CodeMirror-scroll .cm-header{color:#f78553}.cherry.theme__dark .cherry-editor .CodeMirror .CodeMirror-scroll .cm-url{background-color:#000}.cherry.theme__dark .cherry-editor .CodeMirror .CodeMirror-scroll .cm-comment,.cherry.theme__dark .cherry-editor .CodeMirror .CodeMirror-scroll .cm-url{color:#ffcb6b}.cherry.theme__dark .cherry-editor .CodeMirror .CodeMirror-selected{background-color:#454646}.cherry.theme__dark .cherry-sidebar{box-shadow:0 0 10px rgba(128,145,165,.2)}.cherry.theme__dark .cherry-previewer{background-color:#333}.cherry.theme__dark .cherry-previewer .cherry-mobile-previewer-content{background-color:#252526}.cherry.theme__dark .cherry-previewer-table-content-hander .cherry-previewer-table-content-hander__input textarea{background-color:#252526;color:#c8c8c8;outline-color:#f78553}.cherry-markdown.theme__dark{color:#c8c8c8}.cherry-markdown.theme__dark h1,.cherry-markdown.theme__dark h2,.cherry-markdown.theme__dark h3,.cherry-markdown.theme__dark h4,.cherry-markdown.theme__dark h5{color:#f78553}.cherry-markdown.theme__dark ul.cherry-list__upper-roman{list-style:upper-roman}.cherry-markdown.theme__dark ul.cherry-list__lower-greek{list-style:lower-greek}.cherry-markdown.theme__dark ul.cherry-list__cjk-ideographic{list-style:cjk-ideographic}.cherry-markdown.theme__dark ul.cherry-list__circle{list-style:circle}.cherry-markdown.theme__dark ul.cherry-list__square{list-style:square}.cherry-markdown.theme__dark blockquote{color:#c8c8c8}.cherry-markdown.theme__dark a{text-decoration:none;color:#ffcb6b}.cherry-markdown.theme__dark a:hover{color:#f78553}.cherry-markdown.theme__dark hr{border-color:dimgray}.cherry-markdown.theme__dark p code,.cherry-markdown.theme__dark li code{background-color:#000;color:#ffcb6b;border:1px solid dimgray}.cherry-markdown.theme__dark table,.cherry-markdown.theme__dark .cherry-table{color:#c8c8c8}.cherry-markdown.theme__dark table th,.cherry-markdown.theme__dark .cherry-table th{background-color:#000}.cherry-markdown.theme__dark table tr,.cherry-markdown.theme__dark table th,.cherry-markdown.theme__dark table td,.cherry-markdown.theme__dark .cherry-table tr,.cherry-markdown.theme__dark .cherry-table th,.cherry-markdown.theme__dark .cherry-table td{border-color:dimgray}.cherry-markdown.theme__dark .footnote{border-color:dimgray}.cherry-markdown.theme__dark .footnote .footnote-title{background-color:#000}.cherry-markdown.theme__dark .footnote .one-footnote{color:#c8c8c8;border-color:dimgray}.cherry-markdown.theme__dark .footnote .one-footnote a.footnote-ref{padding:5px}.cherry-markdown.theme__dark .toc{border:1px solid dimgray;margin-top:15px;margin-bottom:15px;margin-right:15px}.cherry-markdown.theme__dark .toc .toc-title{padding:15px;margin-bottom:15px;border-bottom:1px solid dimgray}.cherry-markdown.theme__dark .toc .toc-li{border:none;padding:0 20px}.cherry-markdown.theme__dark .toc .toc-li a{color:#c8c8c8}.cherry-markdown.theme__dark .toc .toc-li a:hover{color:#f78553}.cherry-markdown.theme__dark figure svg path,.cherry-markdown.theme__dark figure svg rect,.cherry-markdown.theme__dark figure svg line{stroke:#ffcb6b !important}.cherry-markdown.theme__dark figure svg text{fill:#faa000 !important;stroke:none !important}.cherry-markdown.theme__dark figure svg tspan{fill:#faa000 !important}.cherry-markdown.theme__dark figure svg circle{fill:#ececff !important}.cherry-markdown.theme__dark figure svg circle.state-start{fill:#faa000 !important}.cherry.theme__light .cherry-toolbar,.cherry.theme__light .cherry-floatmenu,.cherry.theme__light .cherry-bubble,.cherry.theme__light .cherry-sidebar{background:#fff;border-color:#fff}.cherry.theme__light .cherry-toolbar .cherry-toolbar-button,.cherry.theme__light .cherry-floatmenu .cherry-toolbar-button,.cherry.theme__light .cherry-bubble .cherry-toolbar-button,.cherry.theme__light .cherry-sidebar .cherry-toolbar-button{color:#3f4a56}.cherry.theme__light .cherry-toolbar .cherry-toolbar-button:hover,.cherry.theme__light .cherry-floatmenu .cherry-toolbar-button:hover,.cherry.theme__light .cherry-bubble .cherry-toolbar-button:hover,.cherry.theme__light .cherry-sidebar .cherry-toolbar-button:hover{background-color:#ebf3ff;color:#5d9bfc !important;border-color:#fff}.cherry.theme__light .cherry-toolbar .cherry-toolbar-button:hover i,.cherry.theme__light .cherry-floatmenu .cherry-toolbar-button:hover i,.cherry.theme__light .cherry-bubble .cherry-toolbar-button:hover i,.cherry.theme__light .cherry-sidebar .cherry-toolbar-button:hover i{color:#5d9bfc !important}.cherry.theme__light .cherry-dropdown{background:#fff}.cherry.theme__light .cherry-dropdown .cherry-dropdown-item{color:#3f4a56}.cherry.theme__light .cherry-dropdown .cherry-dropdown-item:hover{background-color:#ebf3ff;color:#5d9bfc}.cherry.theme__light .cherry-dropdown.cherry-color-wrap h3{color:#3f4a56}.cherry.theme__light .cherry-dropdown.cherry-color-wrap .cherry-color-item{border-color:#ebf3ff}.cherry.theme__light .cherry-dropdown.cherry-color-wrap .cherry-color-item:hover{border-color:#f78553}.cherry.theme__light .cherry-bubble .cherry-bubble-bottom{border-top-color:#fff}.cherry.theme__light .cherry-editor{background-color:#fff}.cherry.theme__light .cherry-editor .CodeMirror{background-color:#fff}.cherry.theme__light .cherry-editor .CodeMirror .CodeMirror-cursor{border-left:1px solid #000}.cherry.theme__light .cherry-editor .CodeMirror .CodeMirror-scroll span,.cherry.theme__light .cherry-editor .CodeMirror .CodeMirror-scroll .cm-variable-2,.cherry.theme__light .cherry-editor .CodeMirror .CodeMirror-scroll .cm-string,.cherry.theme__light .cherry-editor .CodeMirror .CodeMirror-scroll .cm-strong,.cherry.theme__light .cherry-editor .CodeMirror .CodeMirror-scroll .cm-em,.cherry.theme__light .cherry-editor .CodeMirror .CodeMirror-scroll .cm-meta{color:#3f4a56}.cherry.theme__light .cherry-editor .CodeMirror .CodeMirror-scroll .cm-image-marker,.cherry.theme__light .cherry-editor .CodeMirror .CodeMirror-scroll .cm-quote,.cherry.theme__light .cherry-editor .CodeMirror .CodeMirror-scroll .cm-header{color:#228be6}.cherry.theme__light .cherry-editor .CodeMirror .CodeMirror-scroll .cm-url{background-color:#d7e6fe}.cherry.theme__light .cherry-editor .CodeMirror .CodeMirror-scroll .cm-comment,.cherry.theme__light .cherry-editor .CodeMirror .CodeMirror-scroll .cm-url{color:#4dabf7}.cherry.theme__light .cherry-editor .CodeMirror .CodeMirror-selected{background-color:#ebf3ff}.cherry.theme__light .cherry-sidebar{box-shadow:0 0 10px rgba(128,145,165,.2)}.cherry.theme__light .cherry-previewer{background-color:#fff}.cherry.theme__light .cherry-previewer .cherry-mobile-previewer-content{background-color:#fff}.cherry.theme__light .cherry-previewer-table-content-hander .cherry-previewer-table-content-hander__input textarea{background-color:#fff;color:#3f4a56;outline-color:#228be6}.cherry-markdown.theme__light{color:#3f4a56}.cherry-markdown.theme__light h1,.cherry-markdown.theme__light h2,.cherry-markdown.theme__light h3,.cherry-markdown.theme__light h4,.cherry-markdown.theme__light h5{color:#228be6}.cherry-markdown.theme__light ul.cherry-list__upper-roman{list-style:upper-roman}.cherry-markdown.theme__light ul.cherry-list__lower-greek{list-style:lower-greek}.cherry-markdown.theme__light ul.cherry-list__cjk-ideographic{list-style:cjk-ideographic}.cherry-markdown.theme__light ul.cherry-list__circle{list-style:circle}.cherry-markdown.theme__light ul.cherry-list__square{list-style:square}.cherry-markdown.theme__light blockquote{color:#3f4a56;background-color:#e7f5ff;border-color:#1971c2}.cherry-markdown.theme__light a{text-decoration:none;color:#4dabf7}.cherry-markdown.theme__light a:hover{text-decoration:underline;color:#228be6}.cherry-markdown.theme__light hr{border-color:#1971c2}.cherry-markdown.theme__light p code,.cherry-markdown.theme__light li code{background-color:#d7e6fe;color:#4dabf7;border:1px solid #1971c2}.cherry-markdown.theme__light table,.cherry-markdown.theme__light .cherry-table{color:#3f4a56}.cherry-markdown.theme__light table th,.cherry-markdown.theme__light .cherry-table th{background-color:#d7e6fe}.cherry-markdown.theme__light table tr,.cherry-markdown.theme__light table th,.cherry-markdown.theme__light table td,.cherry-markdown.theme__light .cherry-table tr,.cherry-markdown.theme__light .cherry-table th,.cherry-markdown.theme__light .cherry-table td{border-color:#1971c2}.cherry-markdown.theme__light .footnote{border-color:#1971c2}.cherry-markdown.theme__light .footnote .footnote-title{background-color:#d7e6fe}.cherry-markdown.theme__light .footnote .one-footnote{color:#3f4a56;border-color:#1971c2}.cherry-markdown.theme__light .footnote .one-footnote a.footnote-ref{padding:5px}.cherry.theme__green .cherry-toolbar,.cherry.theme__green .cherry-floatmenu,.cherry.theme__green .cherry-bubble,.cherry.theme__green .cherry-sidebar{background:#fff;border-color:#fff}.cherry.theme__green .cherry-toolbar .cherry-toolbar-button,.cherry.theme__green .cherry-floatmenu .cherry-toolbar-button,.cherry.theme__green .cherry-bubble .cherry-toolbar-button,.cherry.theme__green .cherry-sidebar .cherry-toolbar-button{color:#2b8a3e}.cherry.theme__green .cherry-toolbar .cherry-toolbar-button i,.cherry.theme__green .cherry-floatmenu .cherry-toolbar-button i,.cherry.theme__green .cherry-bubble .cherry-toolbar-button i,.cherry.theme__green .cherry-sidebar .cherry-toolbar-button i{color:#2b8a3e}.cherry.theme__green .cherry-toolbar .cherry-toolbar-button:hover,.cherry.theme__green .cherry-floatmenu .cherry-toolbar-button:hover,.cherry.theme__green .cherry-bubble .cherry-toolbar-button:hover,.cherry.theme__green .cherry-sidebar .cherry-toolbar-button:hover{background-color:#51cf66;color:#ebfbee !important;border-color:#fff}.cherry.theme__green .cherry-toolbar .cherry-toolbar-button:hover i,.cherry.theme__green .cherry-floatmenu .cherry-toolbar-button:hover i,.cherry.theme__green .cherry-bubble .cherry-toolbar-button:hover i,.cherry.theme__green .cherry-sidebar .cherry-toolbar-button:hover i{color:#ebfbee !important}.cherry.theme__green .cherry-dropdown{background:#fff}.cherry.theme__green .cherry-dropdown .cherry-dropdown-item{color:#2b8a3e}.cherry.theme__green .cherry-dropdown .cherry-dropdown-item:hover{background-color:#51cf66;color:#ebfbee}.cherry.theme__green .cherry-dropdown.cherry-color-wrap h3{color:#2b8a3e}.cherry.theme__green .cherry-dropdown.cherry-color-wrap .cherry-color-item{border-color:#51cf66}.cherry.theme__green .cherry-dropdown.cherry-color-wrap .cherry-color-item:hover{border-color:#2b8a3e}.cherry.theme__green .cherry-bubble .cherry-bubble-bottom{border-top-color:#fff}.cherry.theme__green .cherry-editor{background-color:#fff}.cherry.theme__green .cherry-editor .CodeMirror{background-color:#fff}.cherry.theme__green .cherry-editor .CodeMirror .CodeMirror-cursor{border-left:1px solid #2b8a3e}.cherry.theme__green .cherry-editor .CodeMirror .CodeMirror-scroll span,.cherry.theme__green .cherry-editor .CodeMirror .CodeMirror-scroll .cm-variable-2,.cherry.theme__green .cherry-editor .CodeMirror .CodeMirror-scroll .cm-string,.cherry.theme__green .cherry-editor .CodeMirror .CodeMirror-scroll .cm-strong,.cherry.theme__green .cherry-editor .CodeMirror .CodeMirror-scroll .cm-em,.cherry.theme__green .cherry-editor .CodeMirror .CodeMirror-scroll .cm-meta{color:#2b8a3e}.cherry.theme__green .cherry-editor .CodeMirror .CodeMirror-scroll .cm-image-marker,.cherry.theme__green .cherry-editor .CodeMirror .CodeMirror-scroll .cm-quote,.cherry.theme__green .cherry-editor .CodeMirror .CodeMirror-scroll .cm-header{color:#37b24d}.cherry.theme__green .cherry-editor .CodeMirror .CodeMirror-scroll .cm-url{background-color:#ebfbee}.cherry.theme__green .cherry-editor .CodeMirror .CodeMirror-scroll .cm-comment,.cherry.theme__green .cherry-editor .CodeMirror .CodeMirror-scroll .cm-url{color:#40c057}.cherry.theme__green .cherry-editor .CodeMirror .CodeMirror-selected{background-color:#b2f2bb}.cherry.theme__green .cherry-sidebar{box-shadow:0 0 10px rgba(128,145,165,.2)}.cherry.theme__green .cherry-previewer{background-color:#ebfbee}.cherry.theme__green .cherry-previewer .cherry-mobile-previewer-content{background-color:#fff}.cherry.theme__green .cherry-previewer-table-content-hander .cherry-previewer-table-content-hander__input textarea{background-color:#fff;color:#2b8a3e;outline-color:#37b24d}.cherry-markdown.theme__green{color:#2b8a3e}.cherry-markdown.theme__green h1,.cherry-markdown.theme__green h2,.cherry-markdown.theme__green h3,.cherry-markdown.theme__green h4,.cherry-markdown.theme__green h5{color:#37b24d;text-align:center;margin-bottom:35px}.cherry-markdown.theme__green ul.cherry-list__upper-roman{list-style:upper-roman}.cherry-markdown.theme__green ul.cherry-list__lower-greek{list-style:lower-greek}.cherry-markdown.theme__green ul.cherry-list__cjk-ideographic{list-style:cjk-ideographic}.cherry-markdown.theme__green ul.cherry-list__circle{list-style:circle}.cherry-markdown.theme__green ul.cherry-list__square{list-style:square}.cherry-markdown.theme__green blockquote{color:#2b8a3e;background-color:#d3f9d8;border-color:#2f9e44}.cherry-markdown.theme__green a{text-decoration:none;color:#40c057}.cherry-markdown.theme__green a:hover{text-decoration:underline;color:#37b24d}.cherry-markdown.theme__green hr{border-color:#2f9e44}.cherry-markdown.theme__green p code,.cherry-markdown.theme__green li code{background-color:#d3f9d8;color:#40c057;border:1px solid #2f9e44}.cherry-markdown.theme__green table,.cherry-markdown.theme__green .cherry-table{color:#2b8a3e}.cherry-markdown.theme__green table th,.cherry-markdown.theme__green .cherry-table th{background-color:#d3f9d8}.cherry-markdown.theme__green table tr,.cherry-markdown.theme__green table th,.cherry-markdown.theme__green table td,.cherry-markdown.theme__green .cherry-table tr,.cherry-markdown.theme__green .cherry-table th,.cherry-markdown.theme__green .cherry-table td{border-color:#2f9e44}.cherry-markdown.theme__green .footnote{border-color:#2f9e44}.cherry-markdown.theme__green .footnote .footnote-title{background-color:#d3f9d8}.cherry-markdown.theme__green .footnote .one-footnote{color:#2b8a3e;border-color:#2f9e44}.cherry-markdown.theme__green .footnote .one-footnote a.footnote-ref{padding:5px}.cherry-markdown.theme__green .toc{border-bottom:1px solid #2f9e44;padding-bottom:15px;margin-bottom:30px}.cherry-markdown.theme__green .toc .toc-title{text-align:center;padding-bottom:15px;margin-top:30px;margin-bottom:15px;border-bottom:1px solid #2f9e44}.cherry-markdown.theme__green .toc .toc-li{border:none}.cherry-markdown.theme__green .toc .toc-li a{color:#2b8a3e}.cherry-markdown.theme__green .toc .toc-li a:hover{color:#37b24d}.cherry.theme__red .cherry-toolbar,.cherry.theme__red .cherry-floatmenu,.cherry.theme__red .cherry-bubble,.cherry.theme__red .cherry-sidebar{background:#ffdeeb;border-color:#ffdeeb}.cherry.theme__red .cherry-toolbar .cherry-toolbar-button,.cherry.theme__red .cherry-floatmenu .cherry-toolbar-button,.cherry.theme__red .cherry-bubble .cherry-toolbar-button,.cherry.theme__red .cherry-sidebar .cherry-toolbar-button{color:#c2255c}.cherry.theme__red .cherry-toolbar .cherry-toolbar-button i,.cherry.theme__red .cherry-floatmenu .cherry-toolbar-button i,.cherry.theme__red .cherry-bubble .cherry-toolbar-button i,.cherry.theme__red .cherry-sidebar .cherry-toolbar-button i{color:#c2255c}.cherry.theme__red .cherry-toolbar .cherry-toolbar-button:hover,.cherry.theme__red .cherry-floatmenu .cherry-toolbar-button:hover,.cherry.theme__red .cherry-bubble .cherry-toolbar-button:hover,.cherry.theme__red .cherry-sidebar .cherry-toolbar-button:hover{background-color:#f06595;color:#fff0f6 !important;border-color:#ffdeeb}.cherry.theme__red .cherry-toolbar .cherry-toolbar-button:hover i,.cherry.theme__red .cherry-floatmenu .cherry-toolbar-button:hover i,.cherry.theme__red .cherry-bubble .cherry-toolbar-button:hover i,.cherry.theme__red .cherry-sidebar .cherry-toolbar-button:hover i{color:#fff0f6 !important}.cherry.theme__red .cherry-dropdown{background:#ffdeeb}.cherry.theme__red .cherry-dropdown .cherry-dropdown-item{color:#c2255c}.cherry.theme__red .cherry-dropdown .cherry-dropdown-item:hover{background-color:#f06595;color:#fff0f6}.cherry.theme__red .cherry-dropdown.cherry-color-wrap h3{color:#c2255c}.cherry.theme__red .cherry-dropdown.cherry-color-wrap .cherry-color-item{border-color:#f06595}.cherry.theme__red .cherry-dropdown.cherry-color-wrap .cherry-color-item:hover{border-color:#a61e4d}.cherry.theme__red .cherry-bubble .cherry-bubble-bottom{border-top-color:#ffdeeb}.cherry.theme__red .cherry-editor{background-color:#fff0f6}.cherry.theme__red .cherry-editor .CodeMirror{background-color:#fff0f6}.cherry.theme__red .cherry-editor .CodeMirror .CodeMirror-cursor{border-left:1px solid #a61e4d}.cherry.theme__red .cherry-editor .CodeMirror .CodeMirror-scroll span,.cherry.theme__red .cherry-editor .CodeMirror .CodeMirror-scroll .cm-variable-2,.cherry.theme__red .cherry-editor .CodeMirror .CodeMirror-scroll .cm-string,.cherry.theme__red .cherry-editor .CodeMirror .CodeMirror-scroll .cm-strong,.cherry.theme__red .cherry-editor .CodeMirror .CodeMirror-scroll .cm-em,.cherry.theme__red .cherry-editor .CodeMirror .CodeMirror-scroll .cm-meta{color:#a61e4d}.cherry.theme__red .cherry-editor .CodeMirror .CodeMirror-scroll .cm-image-marker,.cherry.theme__red .cherry-editor .CodeMirror .CodeMirror-scroll .cm-quote,.cherry.theme__red .cherry-editor .CodeMirror .CodeMirror-scroll .cm-header{color:#d6336c}.cherry.theme__red .cherry-editor .CodeMirror .CodeMirror-scroll .cm-url{background-color:#ffdeeb}.cherry.theme__red .cherry-editor .CodeMirror .CodeMirror-scroll .cm-comment,.cherry.theme__red .cherry-editor .CodeMirror .CodeMirror-scroll .cm-url{color:#f06595}.cherry.theme__red .cherry-editor .CodeMirror .CodeMirror-selected{background-color:#fcc2d7}.cherry.theme__red .cherry-sidebar{box-shadow:0 0 10px #fcc2d7}.cherry.theme__red .cherry-previewer{background-color:#fff0f6}.cherry.theme__red .cherry-previewer .cherry-mobile-previewer-content{background-color:#fff0f6}.cherry.theme__red .cherry-previewer-table-content-hander .cherry-previewer-table-content-hander__input textarea{background-color:#fff0f6;color:#a61e4d;outline-color:#d6336c}.cherry-markdown.theme__red{color:#a61e4d}.cherry-markdown.theme__red h1,.cherry-markdown.theme__red h2,.cherry-markdown.theme__red h3,.cherry-markdown.theme__red h4,.cherry-markdown.theme__red h5{color:#d6336c;text-align:center;border-bottom:1px dashed #c2255c;padding-bottom:15px;margin-bottom:25px}.cherry-markdown.theme__red ul.cherry-list__upper-roman{list-style:upper-roman}.cherry-markdown.theme__red ul.cherry-list__lower-greek{list-style:lower-greek}.cherry-markdown.theme__red ul.cherry-list__cjk-ideographic{list-style:cjk-ideographic}.cherry-markdown.theme__red ul.cherry-list__circle{list-style:circle}.cherry-markdown.theme__red ul.cherry-list__square{list-style:square}.cherry-markdown.theme__red blockquote{color:#a61e4d;background-color:#ffdeeb;border-color:#c2255c}.cherry-markdown.theme__red a{text-decoration:none;color:#f06595}.cherry-markdown.theme__red a:hover{text-decoration:underline;color:#d6336c}.cherry-markdown.theme__red hr{border-color:#c2255c}.cherry-markdown.theme__red p code,.cherry-markdown.theme__red li code{background-color:#ffdeeb;color:#f06595;border:1px solid #c2255c}.cherry-markdown.theme__red table,.cherry-markdown.theme__red .cherry-table{color:#a61e4d}.cherry-markdown.theme__red table th,.cherry-markdown.theme__red .cherry-table th{background-color:#ffdeeb}.cherry-markdown.theme__red table tr,.cherry-markdown.theme__red table th,.cherry-markdown.theme__red table td,.cherry-markdown.theme__red .cherry-table tr,.cherry-markdown.theme__red .cherry-table th,.cherry-markdown.theme__red .cherry-table td{border-color:#c2255c}.cherry-markdown.theme__red .footnote{border-color:#c2255c}.cherry-markdown.theme__red .footnote .footnote-title{background-color:#ffdeeb}.cherry-markdown.theme__red .footnote .one-footnote{color:#a61e4d;border-color:#c2255c}.cherry-markdown.theme__red .footnote .one-footnote a.footnote-ref{padding:5px}.cherry-markdown.theme__red .toc{border-bottom:1px solid #c2255c;padding-bottom:15px;margin-bottom:30px}.cherry-markdown.theme__red .toc .toc-title{text-align:center;padding-bottom:15px;margin-top:30px;margin-bottom:15px;border-bottom:1px solid #c2255c}.cherry-markdown.theme__red .toc .toc-li{border:none}.cherry-markdown.theme__red .toc .toc-li a{color:#a61e4d}.cherry-markdown.theme__red .toc .toc-li a:hover{color:#d6336c}.CodeMirror{font-family:monospace;height:300px;color:#000;direction:ltr}.CodeMirror-lines{padding:4px 0}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{padding:0 4px}.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid #000;border-right:none;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0 !important;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-fat-cursor-mark{background-color:rgba(20,255,20,.5);-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite}.cm-animate-fat-cursor{width:auto;border:0;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite;background-color:#7e7}@-moz-keyframes blink{50%{background-color:rgba(0,0,0,0)}}@-webkit-keyframes blink{50%{background-color:rgba(0,0,0,0)}}@keyframes blink{50%{background-color:rgba(0,0,0,0)}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-rulers{position:absolute;left:0;right:0;top:-50px;bottom:0;overflow:hidden}.CodeMirror-ruler{border-left:1px solid #ccc;top:0;bottom:0;position:absolute}.cm-s-default .cm-header{color:blue}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:bold}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:blue}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3,.cm-s-default .cm-type{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta{color:#555}.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-s-default .cm-error{color:red}.cm-invalidchar{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0b0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#a22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:#fff}.CodeMirror-scroll{overflow:scroll !important;margin-bottom:-50px;margin-right:-50px;padding-bottom:50px;height:100%;outline:none;position:relative}.CodeMirror-sizer{position:relative;border-right:50px solid rgba(0,0,0,0)}.CodeMirror-vscrollbar,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{position:absolute;z-index:6;display:none;outline:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;min-height:100%;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;vertical-align:top;margin-bottom:-50px}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:none !important;border:none !important}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-gutter-wrapper ::selection{background-color:rgba(0,0,0,0)}.CodeMirror-gutter-wrapper ::-moz-selection{background-color:rgba(0,0,0,0)}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:rgba(0,0,0,0);font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-font-variant-ligatures:contextual;font-variant-ligatures:contextual}.CodeMirror-wrap pre.CodeMirror-line,.CodeMirror-wrap pre.CodeMirror-line-like{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;padding:.1px}.CodeMirror-rtl pre{direction:rtl}.CodeMirror-code{outline:none}.CodeMirror-scroll,.CodeMirror-sizer,.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber{-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute;pointer-events:none}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-focused div.CodeMirror-cursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background-color:#ffa;background-color:rgba(255,255,0,.4)}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:""}span.CodeMirror-selectedtext{background:none}
\ No newline at end of file
diff --git a/vscodePlugin/web-resources/dist/cherry-markdown.min.js b/vscodePlugin/web-resources/dist/cherry-markdown.min.js
new file mode 100644
index 000000000..10bad506b
--- /dev/null
+++ b/vscodePlugin/web-resources/dist/cherry-markdown.min.js
@@ -0,0 +1 @@
+!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t=t||self).Cherry={})}(this,(function(t){"use strict";var e="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function n(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}function r(t,e){return t(e={exports:{}},e.exports),e.exports}var i,a,o=function(t){return t&&t.Math==Math&&t},s=o("object"==typeof globalThis&&globalThis)||o("object"==typeof window&&window)||o("object"==typeof self&&self)||o("object"==typeof e&&e)||function(){return this}()||Function("return this")(),l=function(t){try{return!!t()}catch(t){return!0}},A=!l((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")})),u=Function.prototype,h=u.apply,f=u.call,d="object"==typeof Reflect&&Reflect.apply||(A?f.bind(h):function(){return f.apply(h,arguments)}),p=Function.prototype,g=p.bind,m=p.call,y=A&&g.bind(m,m),v=A?function(t){return t&&y(t)}:function(t){return t&&function(){return m.apply(t,arguments)}},b=function(t){return"function"==typeof t},_=!l((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]})),w=Function.prototype.call,E=A?w.bind(w):function(){return w.apply(w,arguments)},C={}.propertyIsEnumerable,x=Object.getOwnPropertyDescriptor,B={f:x&&!C.call({1:2},1)?function(t){var e=x(this,t);return!!e&&e.enumerable}:C},T=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}},k=v({}.toString),S=v("".slice),I=function(t){return S(k(t),8,-1)},L=s.Object,F=v("".split),N=l((function(){return!L("z").propertyIsEnumerable(0)}))?function(t){return"String"==I(t)?F(t,""):L(t)}:L,D=s.TypeError,O=function(t){if(null==t)throw D("Can't call method on "+t);return t},M=function(t){return N(O(t))},R=function(t){return"object"==typeof t?null!==t:b(t)},U={},P=function(t){return b(t)?t:void 0},H=function(t,e){return arguments.length<2?P(U[t])||P(s[t]):U[t]&&U[t][e]||s[t]&&s[t][e]},Q=v({}.isPrototypeOf),G=H("navigator","userAgent")||"",$=s.process,K=s.Deno,j=$&&$.versions||K&&K.version,Y=j&&j.v8;Y&&(a=(i=Y.split("."))[0]>0&&i[0]<4?1:+(i[0]+i[1])),!a&&G&&(!(i=G.match(/Edge\/(\d+)/))||i[1]>=74)&&(i=G.match(/Chrome\/(\d+)/))&&(a=+i[1]);var z=a,W=!!Object.getOwnPropertySymbols&&!l((function(){var t=Symbol();return!String(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&z&&z<41})),V=W&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,q=s.Object,X=V?function(t){return"symbol"==typeof t}:function(t){var e=H("Symbol");return b(e)&&Q(e.prototype,q(t))},J=s.String,Z=function(t){try{return J(t)}catch(t){return"Object"}},tt=s.TypeError,et=function(t){if(b(t))return t;throw tt(Z(t)+" is not a function")},nt=function(t,e){var n=t[e];return null==n?void 0:et(n)},rt=s.TypeError,it=Object.defineProperty,at=s["__core-js_shared__"]||function(t,e){try{it(s,t,{value:e,configurable:!0,writable:!0})}catch(n){s[t]=e}return e}("__core-js_shared__",{}),ot=r((function(t){(t.exports=function(t,e){return at[t]||(at[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.22.6",mode:"pure",copyright:"© 2014-2022 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.22.6/LICENSE",source:"https://github.com/zloirock/core-js"})})),st=s.Object,ct=function(t){return st(O(t))},lt=v({}.hasOwnProperty),At=Object.hasOwn||function(t,e){return lt(ct(t),e)},ut=0,ht=Math.random(),ft=v(1..toString),dt=function(t){return"Symbol("+(void 0===t?"":t)+")_"+ft(++ut+ht,36)},pt=ot("wks"),gt=s.Symbol,mt=gt&>.for,yt=V?gt:gt&>.withoutSetter||dt,vt=function(t){if(!At(pt,t)||!W&&"string"!=typeof pt[t]){var e="Symbol."+t;W&&At(gt,t)?pt[t]=gt[t]:pt[t]=V&&mt?mt(e):yt(e)}return pt[t]},bt=s.TypeError,_t=vt("toPrimitive"),wt=function(t,e){if(!R(t)||X(t))return t;var n,r=nt(t,_t);if(r){if(void 0===e&&(e="default"),n=E(r,t,e),!R(n)||X(n))return n;throw bt("Can't convert object to primitive value")}return void 0===e&&(e="number"),function(t,e){var n,r;if("string"===e&&b(n=t.toString)&&!R(r=E(n,t)))return r;if(b(n=t.valueOf)&&!R(r=E(n,t)))return r;if("string"!==e&&b(n=t.toString)&&!R(r=E(n,t)))return r;throw rt("Can't convert object to primitive value")}(t,e)},Et=function(t){var e=wt(t,"string");return X(e)?e:e+""},Ct=s.document,xt=R(Ct)&&R(Ct.createElement),Bt=function(t){return xt?Ct.createElement(t):{}},Tt=!_&&!l((function(){return 7!=Object.defineProperty(Bt("div"),"a",{get:function(){return 7}}).a})),kt=Object.getOwnPropertyDescriptor,St={f:_?kt:function(t,e){if(t=M(t),e=Et(e),Tt)try{return kt(t,e)}catch(t){}if(At(t,e))return T(!E(B.f,t,e),t[e])}},It=/#|\.prototype\./,Lt=function(t,e){var n=Nt[Ft(t)];return n==Ot||n!=Dt&&(b(e)?l(e):!!e)},Ft=Lt.normalize=function(t){return String(t).replace(It,".").toLowerCase()},Nt=Lt.data={},Dt=Lt.NATIVE="N",Ot=Lt.POLYFILL="P",Mt=Lt,Rt=v(v.bind),Ut=function(t,e){return et(t),void 0===e?t:A?Rt(t,e):function(){return t.apply(e,arguments)}},Pt=_&&l((function(){return 42!=Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype})),Ht=s.String,Qt=s.TypeError,Gt=function(t){if(R(t))return t;throw Qt(Ht(t)+" is not an object")},$t=s.TypeError,Kt=Object.defineProperty,jt=Object.getOwnPropertyDescriptor,Yt={f:_?Pt?function(t,e,n){if(Gt(t),e=Et(e),Gt(n),"function"==typeof t&&"prototype"===e&&"value"in n&&"writable"in n&&!n.writable){var r=jt(t,e);r&&r.writable&&(t[e]=n.value,n={configurable:"configurable"in n?n.configurable:r.configurable,enumerable:"enumerable"in n?n.enumerable:r.enumerable,writable:!1})}return Kt(t,e,n)}:Kt:function(t,e,n){if(Gt(t),e=Et(e),Gt(n),Tt)try{return Kt(t,e,n)}catch(t){}if("get"in n||"set"in n)throw $t("Accessors not supported");return"value"in n&&(t[e]=n.value),t}},zt=_?function(t,e,n){return Yt.f(t,e,T(1,n))}:function(t,e,n){return t[e]=n,t},Wt=St.f,Vt=function(t){var e=function(n,r,i){if(this instanceof e){switch(arguments.length){case 0:return new t;case 1:return new t(n);case 2:return new t(n,r)}return new t(n,r,i)}return d(t,this,arguments)};return e.prototype=t.prototype,e},qt=function(t,e){var n,r,i,a,o,c,l,A,u=t.target,h=t.global,f=t.stat,d=t.proto,p=h?s:f?s[u]:(s[u]||{}).prototype,g=h?U:U[u]||zt(U,u,{})[u],m=g.prototype;for(i in e)n=!Mt(h?i:u+(f?".":"#")+i,t.forced)&&p&&At(p,i),o=g[i],n&&(c=t.dontCallGetSet?(A=Wt(p,i))&&A.value:p[i]),a=n&&c?c:e[i],n&&typeof o==typeof a||(l=t.bind&&n?Ut(a,s):t.wrap&&n?Vt(a):d&&b(a)?v(a):a,(t.sham||a&&a.sham||o&&o.sham)&&zt(l,"sham",!0),zt(g,i,l),d&&(At(U,r=u+"Prototype")||zt(U,r,{}),zt(U[r],i,a),t.real&&m&&!m[i]&&zt(m,i,a)))},Xt=v([].slice),Jt=s.Function,Zt=v([].concat),te=v([].join),ee={},ne=function(t,e,n){if(!At(ee,e)){for(var r=[],i=0;i0?xe:Ce)(e)},Te=function(t){var e=+t;return e!=e||0===e?0:Be(e)},ke=Math.max,Se=Math.min,Ie=function(t,e){var n=Te(t);return n<0?ke(n+e,0):Se(n,e)},Le=Math.min,Fe=function(t){return t>0?Le(Te(t),9007199254740991):0},Ne=function(t){return Fe(t.length)},De=function(t){return function(e,n,r){var i,a=M(e),o=Ne(a),s=Ie(r,o);if(t&&n!=n){for(;o>s;)if((i=a[s++])!=i)return!0}else for(;o>s;s++)if((t||s in a)&&a[s]===n)return t||s||0;return!t&&-1}},Oe={includes:De(!0),indexOf:De(!1)},Me={},Re=Oe.indexOf,Ue=v([].push),Pe=function(t,e){var n,r=M(t),i=0,a=[];for(n in r)!At(Me,n)&&At(r,n)&&Ue(a,n);for(;e.length>i;)At(r,n=e[i++])&&(~Re(a,n)||Ue(a,n));return a},He=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],Qe=Object.keys||function(t){return Pe(t,He)},Ge={f:_&&!Pt?Object.defineProperties:function(t,e){Gt(t);for(var n,r=M(e),i=Qe(e),a=i.length,o=0;a>o;)Yt.f(t,n=i[o++],r[n]);return t}},$e=H("document","documentElement"),Ke=ot("keys"),je=function(t){return Ke[t]||(Ke[t]=dt(t))},Ye=je("IE_PROTO"),ze=function(){},We=function(t){return"
+
+
+