├── .gitignore
├── .npmrc
├── Dockerfile
├── LICENSE
├── README.md
├── arya.config.sample.js
├── commands
├── clear-commit-msg.sh
├── deploy.sh
└── preview.js
├── jest.config.js
├── nginx.conf
├── package.json
├── public
├── favicon.ico
├── img
│ └── icons
│ │ ├── android-chrome-96x96.png
│ │ ├── apple-touch-icon.png
│ │ ├── browserconfig.xml
│ │ ├── favicon-16x16.png
│ │ ├── favicon-32x32.png
│ │ ├── mstile-150x150.png
│ │ └── safari-pinned-tab.svg
├── index.html
├── manifest.json
├── mockup.png
├── robots.txt
├── service-worker.js
└── site.webmanifest
├── src
├── App.vue
├── assets
│ ├── icons
│ │ ├── adjust.svg
│ │ ├── author.svg
│ │ ├── document.svg
│ │ ├── download.svg
│ │ ├── explore.svg
│ │ ├── full-screen.svg
│ │ ├── github.svg
│ │ ├── homepage.svg
│ │ ├── index.js
│ │ ├── preview.svg
│ │ ├── set-style.svg
│ │ ├── setting.svg
│ │ ├── upload.svg
│ │ ├── wechat.svg
│ │ └── x.svg
│ ├── images
│ │ ├── logo.png
│ │ ├── markdown-white.png
│ │ └── markdown.png
│ └── styles
│ │ ├── common.less
│ │ ├── element.less
│ │ ├── element
│ │ ├── alert.css
│ │ ├── aside.css
│ │ ├── autocomplete.css
│ │ ├── badge.css
│ │ ├── base.css
│ │ ├── breadcrumb-item.css
│ │ ├── breadcrumb.css
│ │ ├── button-group.css
│ │ ├── button.css
│ │ ├── card.css
│ │ ├── carousel-item.css
│ │ ├── carousel.css
│ │ ├── cascader.css
│ │ ├── checkbox-button.css
│ │ ├── checkbox-group.css
│ │ ├── checkbox.css
│ │ ├── col.css
│ │ ├── collapse-item.css
│ │ ├── collapse.css
│ │ ├── color-picker.css
│ │ ├── container.css
│ │ ├── date-picker.css
│ │ ├── dialog.css
│ │ ├── display.css
│ │ ├── dropdown-item.css
│ │ ├── dropdown-menu.css
│ │ ├── dropdown.css
│ │ ├── fonts
│ │ │ ├── element-icons.ttf
│ │ │ └── element-icons.woff
│ │ ├── footer.css
│ │ ├── form-item.css
│ │ ├── form.css
│ │ ├── header.css
│ │ ├── icon.css
│ │ ├── index.css
│ │ ├── input-number.css
│ │ ├── input.css
│ │ ├── loading.css
│ │ ├── main.css
│ │ ├── menu-item-group.css
│ │ ├── menu-item.css
│ │ ├── menu.css
│ │ ├── message-box.css
│ │ ├── message.css
│ │ ├── notification.css
│ │ ├── option-group.css
│ │ ├── option.css
│ │ ├── pagination.css
│ │ ├── popover.css
│ │ ├── popper.css
│ │ ├── progress.css
│ │ ├── radio-button.css
│ │ ├── radio-group.css
│ │ ├── radio.css
│ │ ├── rate.css
│ │ ├── reset.css
│ │ ├── row.css
│ │ ├── scrollbar.css
│ │ ├── select-dropdown.css
│ │ ├── select.css
│ │ ├── slider.css
│ │ ├── spinner.css
│ │ ├── step.css
│ │ ├── steps.css
│ │ ├── submenu.css
│ │ ├── switch.css
│ │ ├── tab-pane.css
│ │ ├── table-column.css
│ │ ├── table.css
│ │ ├── tabs.css
│ │ ├── tag.css
│ │ ├── time-picker.css
│ │ ├── time-select.css
│ │ ├── tooltip.css
│ │ ├── transfer.css
│ │ ├── tree.css
│ │ └── upload.css
│ │ ├── mixins.less
│ │ ├── style.less
│ │ └── variables.less
├── components
│ ├── Advertisement.vue
│ ├── Icon.vue
│ ├── PreviewVditor.vue
│ └── icons
│ │ └── Arrow.vue
├── config
│ ├── aboutArya.js
│ ├── constant.js
│ └── default.js
├── global.js
├── helper
│ ├── document.js
│ ├── export.js
│ ├── index.js
│ ├── lodash.js
│ └── utils.js
├── main.js
├── mixins
│ └── metaMixin.js
├── pages
│ ├── About.vue
│ ├── ExportImage.vue
│ ├── ExportPPT.vue
│ ├── ExportPdf.vue
│ ├── Main.vue
│ └── partials
│ │ ├── Frame.vue
│ │ ├── HeaderNav.vue
│ │ └── NotFound.vue
├── registerServiceWorker.js
└── router
│ ├── beforeEachHooks.js
│ ├── commonRoutes.js
│ ├── index.js
│ └── routes
│ ├── index.js
│ └── main.js
├── tests
└── unit
│ ├── .eslintrc.js
│ └── Arrow.spec.js
├── vue.config.js
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | arya.config.js
6 |
7 | # package-lock
8 | package-lock.json
9 |
10 | # ignore json
11 | size-plugin.json
12 |
13 | # local env files
14 | .env.local
15 | .env.*.local
16 |
17 | # Log files
18 | npm-debug.log*
19 | yarn-debug.log*
20 | yarn-error.log*
21 |
22 | # Editor directories and files
23 | .idea
24 | .vscode
25 | *.suo
26 | *.ntvs*
27 | *.njsproj
28 | *.sln
29 | *.sw*
30 |
31 | # Test
32 | tests/coverage
33 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | registry="https://registry.npmmirror.com"
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM nginx:alpine
2 |
3 | COPY dist /usr/share/nginx/html
4 | COPY nginx.conf /etc/nginx/conf.d/default.conf
5 |
6 | EXPOSE 80
7 |
8 | CMD ["nginx", "-g", "daemon off;"]
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 JadeYang(杨琼璞)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |

2 |
3 |
6 |
7 |
8 |
9 | 📝 基于 Vue2、Vditor,所构建的在线 Markdown 编辑器,支持绘制流程图、甘特图、时序图、任务列表、Echarts 图表、五线谱,以及 PPT 预览、视频音频解析、HTML 自动转换为 Markdown 等功能。markdown.lovejade.cn。
10 |
11 |
12 |
13 |
14 |
15 |
41 |
42 | ## 背景初衷
43 |
44 | 早期就有关注到由`黑客派`所出品的 [Vditor](https://github.com/Vanessa219/vditor):一款为未来而构建的下一代 Markdown 编辑器。然,现而今市面上所存在的 Markdown 编辑器,或多或少都存在一些问题(或功能不全,或高级功能收费...),因此基于自身所需,加之 [Vditor](https://github.com/Vanessa219/vditor) 的强大,就诞生了做一款[在线 Markdown 编辑器](https://markdown.lovejade.cn/?ref=github.com) 的念头;取其名曰 [`Arya`(二丫)](https://quickapp.lovejade.cn/talking-game-of-thrones/?ref=github.com)。
45 |
46 | ## 功能支持
47 |
48 | - [x] 🎉 通常 `Markdown` 解析器自带的基本功能;
49 | - [x] 🍀 支持**流程图**、**甘特图**、**时序图**、**任务列表**;
50 | - [x] 🏁 支持粘贴 HTML 自动转换为 Markdown;
51 | - [x] 💃🏻 支持插入原生 Emoji、设置常用表情列表;
52 | - [x] 🚑 支持编辑内容保存**本地存储**,防止意外丢失;
53 | - [x] 📝 支持**实时预览**,主窗口大小拖拽,字符计数;
54 | - [x] 🛠 支持常用快捷键(**Tab**),及代码块添加复制;
55 | - [x] ✨ 支持**导出**携带样式的 PDF、PNG、JPEG 等;
56 | - [x] ✨ 升级 Vditor,新增对 `echarts` 图表的支持;
57 | - [x] ✨ 注入 [RevealJs](https://revealjs.com/#/),增设对 `PPT` 预览支持;
58 | - [x] 👏 支持检查并格式化 Markdown 语法,使其专业;
59 | - [x] 🦑 支持五线谱、及[部分站点、视频、音频解析](https://github.com/Vanessa219/vditor);
60 | - [x] 🌟 增加对**所见即所得**编辑模式的支持(`⌘-⇧-M`);
61 | - [x] 🌟 新增复制到微信公众号等周边功能;
62 | - [x] 🌟 支持导入本地 Markdown(`*.md`) 文件;
63 |
64 | ## 如何使用
65 |
66 | 清空目前 [Arya](https://markdown.lovejade.cn/?ref=github.com) 编辑区默认文档,即可使用。
67 |
68 | 默认为[所见即所得](https://b3log.org/vditor/)模式,可通过 `⌘-⇧-M`(`Ctrl-⇧-M`)进行切换;或通过以下方式:
69 |
70 | - 所见即所得:`⌘-⌥-7`(`Ctrl-alt-7`);
71 | - 即时渲染:`⌘-⌥-8`(`Ctrl-alt-8`);
72 | - 分屏渲染:`⌘-⌥-9`(`Ctrl-alt-9`);
73 |
74 | ### PPT 预览
75 |
76 | 如果您用作 `PPT` 预览(入口在`设置`中),需要注意,这里暂还不能支持各种图表的渲染;您可以使用 `---` 来定义水平方向上幻灯片,用 `--` 来定义垂直幻灯片;更多设定可以参见 [Reveal.js Markdown 文档](https://revealjs.com/markdown/)。
77 |
78 | ## 如何部署?
79 |
80 | ### 采用 [pm2](https://pm2.keymetrics.io/) 部署
81 |
82 | PM2 是一个强大的生产环境进程管理器,它不仅支持通过命令行启动应用,还可以使用配置文件(通常名为 `ecosystem.config.js`)来管理复杂的部署场景。您可以通过执行如下命令实现快速部署:
83 |
84 | ```bash
85 | # 🎉 克隆项目
86 | git clone https://github.com/nicejade/markdown-online-editor.git
87 | cd markdown-online-editor
88 |
89 | # ➕ 安装依赖
90 | yarn
91 | yarn global add pm2
92 |
93 | # 🔧 构建产物
94 | yarn build
95 |
96 | # 🚀 部署服务
97 | cd dist
98 | npx pm2 start "npx http-server -p 8866" --name "markdown-editor"
99 | ```
100 |
101 | ### Docker 自托管
102 |
103 | 已将最新版本使用 [Docker](https://docs.docker.com/engine/install/) 打包镜像并上传至 [Docker Hub](https://hub.docker.com/r/nicejade/markdown-online-editor),可通过如下方式进行使用:
104 |
105 | ```shell
106 | docker run -d -p [Your-Specified-Port]:80 nicejade/markdown-online-editor:[tagname]
107 |
108 | # 示例:
109 | docker run -d -p 8866:80 nicejade/markdown-online-editor:latest
110 | ```
111 |
112 | 基于如上示例,如果您在本地执行,只需打开网址——[http://localhost:8866](http://localhost:8866/) 即可访问。如果在服务器运行,可以通过 http://[Server-IP]:8866 来访问。构建 Docker 镜像过程,可参见:[如何为 markdown-online-editor 服务构建 docker 镜像?](https://memo.lovejade.cn/m/49a7b493bddeed71)。您也可以通过 **Cloudflare Pages** 或 Github Pages,托管编译产物(`dist` 目录下内容),从而实现**无需服务器情况下快速部署**。
113 |
114 | 或者**使用 [docker compose](https://docs.docker.com/compose/)**:
115 |
116 | 创建一个 `docker-compose.yml` 文件,并在其中定义服务(其中 version: '3' 指定了 Docker Compose 文件的版本;您可以根据实际情况进行调整):
117 |
118 | ```yaml
119 | version: '3'
120 | services:
121 | markdown-editor:
122 | image: nicejade/markdown-online-editor:latest
123 | ports:
124 | - '8866:80'
125 | restart: always
126 | ```
127 |
128 | 在包含 `docker-compose.yml` 文件的目录中,运行以下命令启动服务:
129 |
130 | ```bash
131 | docker-compose up -d
132 | ```
133 |
134 | 这将在后台启动服务,并且效果与下面的 `docker run` 命令相同。使用 Docker Compose 可以更方便地管理多个容器,并且配置更易读和维护。
135 |
136 | ## 如何开发
137 |
138 | ### 先决条件
139 |
140 | 说明用户在安装和使用前,需要准备的一些先决条件,譬如:您需要安装或升级 [Node.js](https://nodejs.org/en/)(>= `16.*`,< `18.*`),推荐使用 [Pnpm](https://pnpm.io/) 或 [Yarn](https://www.jeffjade.com/2017/12/30/135-npm-vs-yarn-detial-memo/) 作为首选包管理工具。
141 |
142 | ```bash
143 | # 🎉 克隆项目
144 | git clone https://github.com/nicejade/markdown-online-editor.git
145 | cd markdown-online-editor
146 |
147 | # ➕ 安装依赖
148 | yarn
149 |
150 | # 🚧 开始开发
151 | yarn start
152 |
153 | # 🚀 部署 Github Pages(需修改 commands/deploy.sh)
154 | yarn deploy
155 | ```
156 |
157 | ## 特别鸣谢
158 |
159 | [Arya](https://markdown.lovejade.cn/?utm_source=github.com) 的产生,得益于 [Vditor](https://github.com/b3log/vditor):一款浏览器端的 Markdown 编辑器,同时也离不开 [Vue、Reveal.js 等开源库](https://github.com/nicejade/markdown-online-editor/blob/master/package.json#L25-L64)的支持,感谢 🙌。
160 |
161 | ## 相关链接
162 |
163 | - [清风明月轩](https://www.thebettersites.com/?ref=github.com)
164 | - [逍遥自在轩](https://www.niceshare.site/?ref=github.com)
165 | - [晚晴幽草轩](https://www.jeffjade.com/nicelinks?ref=github.com)
166 | - [缘知随心庭](https://fine.niceshare.site/?ref=github.com)
167 | - [静轩之别苑](https://quickapp.lovejade.cn/?ref=github.com)
168 | - [悠然宜想亭](https://forum.lovejade.cn/?ref=github.com)
169 | - [SegmentFault](https://segmentfault.com/u/jeffjade)
170 | - [X(Twitter)](https://x.com/MarshalXuan)
171 | - [@MarshalXuan](https://www.youtube.com/@MarshalXuan)
172 |
173 | ## License
174 |
175 | [MIT](http://opensource.org/licenses/MIT)
176 |
177 | Copyright (c) 2018-present, [nicejade](https://www.thebettersites.com).
178 |
--------------------------------------------------------------------------------
/arya.config.sample.js:
--------------------------------------------------------------------------------
1 | /** @format */
2 |
3 | /**
4 | * @desc executablePath: Path to a Chromium or Chrome executable to run instead of the bundled Chromium.
5 | * https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions
6 | * 此项目 prerender-spa-plugin 来预渲染 HTML;而此库基于 Puppeteer 所完成;
7 | * 因此在安装时需要下载 Chromium,详见:https://www.jeffjade.com/2019/06/14/156-puppeteer-robot/#%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85
8 | * 推荐手动下载 Chromium,通过设定 executablePath 来使用;在根目录下创建 arya.config.js,其格式如下示例;
9 | */
10 | exports.executablePath = '/Users/${YOUR-PATH}/Chromium.app/Contents/MacOS/Chromium'
11 |
--------------------------------------------------------------------------------
/commands/clear-commit-msg.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | set -e
4 |
5 | git checkout --orphan latest_branch
6 |
7 | git add -A
8 |
9 | git commit -am "✨ initial create & commit"
10 |
11 | git branch -D master
12 |
13 | git branch -m master
14 |
15 | git push -f origin master
16 |
--------------------------------------------------------------------------------
/commands/deploy.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # 确保脚本抛出遇到的错误
4 | set -e
5 |
6 | # 生成静态文件
7 | yarn run build
8 |
9 | # 进入生成的文件夹
10 | cd ./dist
11 |
12 | # 如果是发布到自定义域名
13 | echo 'markdown.lovejade.cn' > CNAME
14 |
15 | git init
16 | git add -A
17 | git commit -m '🎉 update release'
18 |
19 | git push -f git@github.com:nicejade/markdown-online-editor.git main:gh-pages
20 | cd -
--------------------------------------------------------------------------------
/commands/preview.js:
--------------------------------------------------------------------------------
1 | const express = require('express')
2 | const chalk = require('chalk')
3 | const childProcess = require('child_process')
4 | const fs = require('fs')
5 | const path = require('path')
6 | const opn = require('opn')
7 |
8 | const app = express()
9 |
10 | const resolveRealPath = (dir) => {
11 | return path.join(__dirname, dir)
12 | }
13 |
14 | const entryFilePath = resolveRealPath('../dist/index.html')
15 |
16 | const openStaticServer = () => {
17 | app.use('/js', express.static(resolveRealPath('../dist/js/')))
18 | app.use('/css', express.static(resolveRealPath('../dist/css/')))
19 | app.use('/img', express.static(resolveRealPath('../dist/img/')))
20 | app.use('/fonts', express.static(resolveRealPath('../dist/fonts/')))
21 |
22 | app.get('*', function (req, res) {
23 | const content = fs.readFileSync(entryFilePath, 'utf8')
24 | res.send(content)
25 | })
26 |
27 | app.listen(3000, function () {
28 | console.log(chalk.cyan('Example app listening on port 3000!\n'))
29 | console.log(chalk.yellow('You Can Visit: ') + chalk.green('http://localhost:3000/'))
30 | opn('http://localhost:3000')
31 | })
32 | }
33 |
34 | const main = () => {
35 | const isExist = fs.existsSync(entryFilePath)
36 | if (isExist) {
37 | openStaticServer()
38 | } else {
39 | const commandStr = `vue-cli-service build`
40 | const output = childProcess.execSync(commandStr, {
41 | cwd: process.cwd(),
42 | timeout: 60000,
43 | encoding: 'utf8'
44 | })
45 | openStaticServer()
46 | console.log(output)
47 | }
48 | }
49 |
50 | main()
51 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | /** @format */
2 | const path = require('path')
3 |
4 | module.exports = {
5 | moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
6 | transform: {
7 | '^.+\\.vue$': 'vue-jest',
8 | '.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$':
9 | 'jest-transform-stub',
10 | '^.+\\.jsx?$': 'babel-jest'
11 | },
12 | moduleNameMapper: {
13 | '^@/(.*)$': '/src/$1'
14 | },
15 | snapshotSerializers: ['jest-serializer-vue'],
16 | testMatch: [
17 | '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
18 | ],
19 | collectCoverage: true,
20 | collectCoverageFrom: ['src/**/*.{js,vue}', '!src/assets/**'],
21 | coverageReporters: ['html', 'text-summary'],
22 | coverageDirectory: path.resolve(__dirname, './tests/coverage')
23 | }
24 |
--------------------------------------------------------------------------------
/nginx.conf:
--------------------------------------------------------------------------------
1 | server {
2 | listen 80;
3 | server_name _;
4 | root /usr/share/nginx/html;
5 | index index.html;
6 |
7 | # 禁止缓存,确保始终从服务器获取最新内容
8 | add_header Cache-Control no-cache;
9 |
10 | # 处理所有路由
11 | location / {
12 | try_files $uri $uri/ /index.html;
13 |
14 | # 允许所有跨域请求
15 | add_header Access-Control-Allow-Origin *;
16 | add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
17 | add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
18 | }
19 |
20 | # 配置静态资源缓存
21 | location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
22 | expires 1y;
23 | add_header Cache-Control "public, no-transform";
24 | }
25 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "markdown-online-editor",
3 | "version": "3.0.0",
4 | "author": "nicejade",
5 | "private": true,
6 | "description": "Arya,是一款基于 Vue、Vditor,为未来而构建的在线 Markdown 编辑器;轻量且强大:内置粘贴 HTML 自动转换为 Markdown,支持 PPT 预览,以及绘制流程图、甘特图、时序图、任务列表、五线谱,可导出携带样式的图片、PDF、微信公众号特制的 HTML 等。",
7 | "scripts": {
8 | "start": "yarn serve",
9 | "serve": "vue-cli-service serve --open",
10 | "build": "vue-cli-service build",
11 | "watcher": "onchange \"src/**/**/*.{js,css,scss,vue}\" -- prettier --write {{changed}}",
12 | "prettier": "prettier --write \"src/**/**/*.{js,css,scss,vue}\"",
13 | "lint": "vue-cli-service lint",
14 | "test": "vue-cli-service test:unit",
15 | "testbuild": "vue-cli-service build --mode development",
16 | "deploy": "bash ./commands/deploy.sh",
17 | "analyz": "NODE_ENV=production npm_config_report=true npm run build",
18 | "clear-commit-msg": "bash ./commands/clear-commit-msg.sh",
19 | "eslint-fix": "eslint src/**/**/*.vue --fix",
20 | "format-code": "prettier-eslint --write \"src/**/*.{js,vue,css,scss}\"",
21 | "precommit-msg": "echo '🐉 Start pre-commit checks...' && exit 0",
22 | "preview": "node ./commands/preview.js"
23 | },
24 | "dependencies": {
25 | "canvg": "^2.0.0",
26 | "element-ui": "^2.12.0",
27 | "hint.css": "^2.6.0",
28 | "html2canvas": "^1.0.0-rc.3",
29 | "html2pdf.js": "^0.9.1",
30 | "lodash": "4.17.15",
31 | "lodash.assign": "^4.2.0",
32 | "lodash.clonedeep": "^4.5.0",
33 | "register-service-worker": "^1.0.0",
34 | "reveal.js": "^3.8.0",
35 | "vditor": "3.10.8",
36 | "vue": "^2.5.17",
37 | "vue-meta": "^2.2.2",
38 | "vue-router": "^3.1.3"
39 | },
40 | "devDependencies": {
41 | "@vue/cli-plugin-babel": "^3.11.0",
42 | "@vue/cli-plugin-eslint": "^3.11.0",
43 | "@vue/cli-plugin-pwa": "^3.11.0",
44 | "@vue/cli-plugin-unit-jest": "^3.11.0",
45 | "@vue/cli-service": "^3.11.0",
46 | "@vue/test-utils": "^1.0.0-beta.29",
47 | "babel-core": "7.0.0-bridge.0",
48 | "babel-jest": "^24.9.0",
49 | "css-loader": "^3.4.2",
50 | "eslint-config-prettier": "^6.3.0",
51 | "eslint-plugin-prettier": "^3.1.0",
52 | "eslint-plugin-vue": "^5.2.3",
53 | "husky": "^3.0.5",
54 | "less": "^3.11.1",
55 | "less-loader": "^5.0.0",
56 | "lint-staged": "^9.2.5",
57 | "onchange": "^6.1.0",
58 | "prettier-eslint-cli": "^5.0.0",
59 | "size-plugin": "^2.0.0",
60 | "svg-sprite-loader": "^4.1.6",
61 | "svgo-loader": "2.2.1",
62 | "vue-svg-loader": "^0.12.0",
63 | "vue-template-compiler": "^2.5.17",
64 | "webpack-bundle-analyzer": "3.5.0"
65 | },
66 | "babel": {
67 | "presets": [
68 | "@vue/app"
69 | ]
70 | },
71 | "eslintConfig": {
72 | "globals": {
73 | "L": true
74 | },
75 | "root": true,
76 | "env": {
77 | "node": true,
78 | "es6": true
79 | },
80 | "rules": {
81 | "no-console": 0,
82 | "no-useless-escape": 0,
83 | "no-multiple-empty-lines": [
84 | 2,
85 | {
86 | "max": 3
87 | }
88 | ],
89 | "prettier/prettier": [
90 | "error",
91 | {
92 | "singleQuote": true,
93 | "semi": false,
94 | "trailingComma": "none",
95 | "bracketSpacing": true,
96 | "jsxBracketSameLine": true,
97 | "insertPragma": true,
98 | "requirePragma": false
99 | }
100 | ]
101 | },
102 | "plugins": [],
103 | "extends": [
104 | "plugin:vue/essential",
105 | "plugin:prettier/recommended",
106 | "eslint:recommended"
107 | ],
108 | "parserOptions": {
109 | "parser": "babel-eslint"
110 | }
111 | },
112 | "prettier": {
113 | "singleQuote": true,
114 | "semi": false,
115 | "printWidth": 100,
116 | "proseWrap": "never"
117 | },
118 | "postcss": {
119 | "plugins": {
120 | "autoprefixer": {}
121 | }
122 | },
123 | "browserslist": [
124 | "> 1%",
125 | "last 2 versions",
126 | "not ie <= 8"
127 | ],
128 | "eslintIgnore": [
129 | "package.json"
130 | ],
131 | "husky": {
132 | "hooks": {
133 | "pre-commit": "yarn run precommit-msg && lint-staged"
134 | }
135 | },
136 | "lint-staged": {
137 | "**/**.{js,json,pcss,vue,css,scss}": [
138 | "prettier --write"
139 | ]
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/public/favicon.ico
--------------------------------------------------------------------------------
/public/img/icons/android-chrome-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/public/img/icons/android-chrome-96x96.png
--------------------------------------------------------------------------------
/public/img/icons/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/public/img/icons/apple-touch-icon.png
--------------------------------------------------------------------------------
/public/img/icons/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | #00aba9
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/public/img/icons/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/public/img/icons/favicon-16x16.png
--------------------------------------------------------------------------------
/public/img/icons/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/public/img/icons/favicon-32x32.png
--------------------------------------------------------------------------------
/public/img/icons/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/public/img/icons/mstile-150x150.png
--------------------------------------------------------------------------------
/public/img/icons/safari-pinned-tab.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
21 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Arya - 在线 Markdown 编辑器
11 |
13 |
15 |
16 |
17 |
18 |
19 |
21 |
22 |
23 |
24 |
25 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
42 |
43 |
44 |
45 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Markdown \u7f16\u8f91\u5668",
3 | "short_name": "Markdown \u7f16\u8f91\u5668",
4 | "icons": [
5 | {
6 | "src": "/android-chrome-96x96.png",
7 | "sizes": "96x96",
8 | "type": "image/png"
9 | }
10 | ],
11 | "theme_color": "#ffffff",
12 | "background_color": "#ffffff",
13 | "display": "standalone",
14 | "start_url": "https://markdown.lovejade.cn/?utm_source=device-screen"
15 | }
--------------------------------------------------------------------------------
/public/mockup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/public/mockup.png
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow:
3 |
--------------------------------------------------------------------------------
/public/service-worker.js:
--------------------------------------------------------------------------------
1 | const HTMLToCache = '/'
2 | const version = 'v2.1.2'
3 |
4 | self.addEventListener('install', (event) => {
5 | event.waitUntil(
6 | caches.open(version).then((cache) => {
7 | cache.add(HTMLToCache).then(self.skipWaiting())
8 | })
9 | )
10 | })
11 |
12 | self.addEventListener('activate', (event) => {
13 | event.waitUntil(
14 | caches
15 | .keys()
16 | .then((cacheNames) =>
17 | Promise.all(
18 | cacheNames.map((cacheName) => {
19 | if (version !== cacheName) return caches.delete(cacheName)
20 | })
21 | )
22 | )
23 | .then(self.clients.claim())
24 | )
25 | })
26 |
27 | self.addEventListener('fetch', (event) => {
28 | const requestToFetch = event.request.clone()
29 | event.respondWith(
30 | caches.match(event.request.clone()).then((cached) => {
31 | // We don't return cached HTML (except if fetch failed)
32 | if (cached) {
33 | const resourceType = cached.headers.get('content-type')
34 | // We only return non css/js/html cached response e.g images
35 | if (!hasHash(event.request.url) && !/text\/html/.test(resourceType)) {
36 | return cached
37 | }
38 |
39 | // If the CSS/JS didn't change since it's been cached, return the cached version
40 | if (hasHash(event.request.url) && hasSameHash(event.request.url, cached.url)) {
41 | return cached
42 | }
43 | }
44 | return fetch(requestToFetch)
45 | .then((response) => {
46 | const clonedResponse = response.clone()
47 | const contentType = clonedResponse.headers.get('content-type')
48 |
49 | if (
50 | !clonedResponse ||
51 | clonedResponse.status !== 200 ||
52 | clonedResponse.type !== 'basic' ||
53 | /\/sockjs\//.test(event.request.url)
54 | ) {
55 | return response
56 | }
57 |
58 | if (/html/.test(contentType)) {
59 | caches.open(version).then((cache) => cache.put(HTMLToCache, clonedResponse))
60 | } else {
61 | // Delete old version of a file
62 | if (hasHash(event.request.url)) {
63 | caches.open(version).then((cache) =>
64 | cache.keys().then((keys) =>
65 | keys.forEach((asset) => {
66 | if (new RegExp(removeHash(event.request.url)).test(removeHash(asset.url))) {
67 | cache.delete(asset)
68 | }
69 | })
70 | )
71 | )
72 | }
73 |
74 | if (requestToFetch.url.startsWith('http')) {
75 | caches.open(version).then((cache) => cache.put(event.request, clonedResponse))
76 | }
77 | }
78 | return response
79 | })
80 | .catch(() => {
81 | if (hasHash(event.request.url)) return caches.match(event.request.url)
82 | // If the request URL hasn't been served from cache and isn't sockjs we suppose it's HTML
83 | else if (!/\/sockjs\//.test(event.request.url)) return caches.match(HTMLToCache)
84 | // Only for sockjs
85 | return new Response('No connection to the server', {
86 | status: 503,
87 | statusText: 'No connection to the server',
88 | headers: new Headers({ 'Content-Type': 'text/plain' }),
89 | })
90 | })
91 | })
92 | )
93 | })
94 |
95 | function removeHash(element) {
96 | if (typeof element === 'string') return element.split('?hash=')[0]
97 | }
98 |
99 | function hasHash(element) {
100 | if (typeof element === 'string') return /\?hash=.*/.test(element)
101 | }
102 |
103 | function hasSameHash(firstUrl, secondUrl) {
104 | if (typeof firstUrl === 'string' && typeof secondUrl === 'string') {
105 | return /\?hash=(.*)/.exec(firstUrl)[1] === /\?hash=(.*)/.exec(secondUrl)[1]
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Markdown \u7f16\u8f91\u5668",
3 | "short_name": "Markdown \u7f16\u8f91\u5668",
4 | "icons": [
5 | {
6 | "src": "/android-chrome-96x96.png",
7 | "sizes": "96x96",
8 | "type": "image/png"
9 | }
10 | ],
11 | "theme_color": "#ffffff",
12 | "background_color": "#ffffff",
13 | "display": "standalone",
14 | "start_url": "https://markdown.lovejade.cn/?utm_source=device-screen"
15 | }
16 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
16 |
17 |
30 |
--------------------------------------------------------------------------------
/src/assets/icons/adjust.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
47 |
--------------------------------------------------------------------------------
/src/assets/icons/author.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
40 |
--------------------------------------------------------------------------------
/src/assets/icons/document.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
66 |
--------------------------------------------------------------------------------
/src/assets/icons/download.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
51 |
--------------------------------------------------------------------------------
/src/assets/icons/full-screen.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
55 |
--------------------------------------------------------------------------------
/src/assets/icons/github.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
60 |
--------------------------------------------------------------------------------
/src/assets/icons/homepage.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/index.js:
--------------------------------------------------------------------------------
1 | /** @format */
2 |
3 | const files = require.context('.', true, /\.svg$/)
4 | const modules = {}
5 |
6 | files.keys().forEach(key => {
7 | modules[key.replace(/(\.\/|\.svg)/g, '')] = files(key)
8 | })
9 |
10 | export default modules
11 |
--------------------------------------------------------------------------------
/src/assets/icons/preview.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
37 |
--------------------------------------------------------------------------------
/src/assets/icons/set-style.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
48 |
--------------------------------------------------------------------------------
/src/assets/icons/setting.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
57 |
--------------------------------------------------------------------------------
/src/assets/icons/upload.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
51 |
--------------------------------------------------------------------------------
/src/assets/icons/wechat.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/icons/x.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/src/assets/images/logo.png
--------------------------------------------------------------------------------
/src/assets/images/markdown-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/src/assets/images/markdown-white.png
--------------------------------------------------------------------------------
/src/assets/images/markdown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/src/assets/images/markdown.png
--------------------------------------------------------------------------------
/src/assets/styles/common.less:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | box-sizing: border-box;
5 | font-family: Open Sans;
6 | }
7 |
8 | *:focus {
9 | outline: none !important;
10 | }
11 |
12 | a {
13 | color: @brand;
14 | text-decoration: none;
15 | }
16 |
17 | html,
18 | body {
19 | font-size: 14px;
20 | background-color: #ffffff !important;
21 | }
22 | // export page css
23 | .export-page {
24 | width: 100%;
25 | height: 100%;
26 | min-height: 100vh;
27 | background-color: @white;
28 | .flex-box-center(column);
29 | .button-group {
30 | width: 100%;
31 | margin: 20px auto;
32 | }
33 | #export-vditor {
34 | max-width: 960px;
35 | height: 100%;
36 | min-height: 100vh;
37 | margin-bottom: 20px;
38 | text-align: left;
39 | }
40 | .vditor-toolbar {
41 | display: none;
42 | }
43 | .vditor {
44 | border: 0;
45 | }
46 | .vditor-preview {
47 | padding: 3 * @size-factor;
48 | margin: 3 * @size-factor;
49 | box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
50 | }
51 | .vditor-reset h1 {
52 | text-align: center;
53 | }
54 | }
55 |
56 | @media (max-width: 768px) {
57 | .export-page {
58 | #export-vditor {
59 | width: 100% !important;
60 | margin: 0 !important;
61 | }
62 | .vditor-preview {
63 | padding: 0 10px;
64 | }
65 | }
66 | }
67 |
68 | #khaleesi {
69 | text-align: left;
70 | }
71 |
--------------------------------------------------------------------------------
/src/assets/styles/element.less:
--------------------------------------------------------------------------------
1 | .el-message {
2 | z-index: @el-message-zindex !important;
3 | }
4 | .el-dropdown-menu__item {
5 | a {
6 | color: #606266;
7 | }
8 | }
9 | .el-dropdown-menu__item.is-disabled {
10 | a {
11 | color: #bbbbbb;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/assets/styles/element/alert.css:
--------------------------------------------------------------------------------
1 | .el-alert {
2 | width: 100%;
3 | padding: 8px 16px;
4 | margin: 0;
5 | -webkit-box-sizing: border-box;
6 | box-sizing: border-box;
7 | border-radius: 4px;
8 | position: relative;
9 | background-color: #fff;
10 | overflow: hidden;
11 | opacity: 1;
12 | display: -webkit-box;
13 | display: -ms-flexbox;
14 | display: flex;
15 | -webkit-box-align: center;
16 | -ms-flex-align: center;
17 | align-items: center;
18 | -webkit-transition: opacity 0.2s;
19 | transition: opacity 0.2s;
20 | }
21 | .el-alert.is-center {
22 | -webkit-box-pack: center;
23 | -ms-flex-pack: center;
24 | justify-content: center;
25 | }
26 | .el-alert--success {
27 | background-color: #f0f9eb;
28 | color: #67c23a;
29 | }
30 | .el-alert--success .el-alert__description {
31 | color: #67c23a;
32 | }
33 | .el-alert--info {
34 | background-color: #f4f4f5;
35 | color: #909399;
36 | }
37 | .el-alert--info .el-alert__description {
38 | color: #909399;
39 | }
40 | .el-alert--warning {
41 | background-color: #fdf6ec;
42 | color: #e6a23c;
43 | }
44 | .el-alert--warning .el-alert__description {
45 | color: #e6a23c;
46 | }
47 | .el-alert--error {
48 | background-color: #fef0f0;
49 | color: #f56c6c;
50 | }
51 | .el-alert--error .el-alert__description {
52 | color: #f56c6c;
53 | }
54 | .el-alert__content {
55 | display: table-cell;
56 | padding: 0 8px;
57 | }
58 | .el-alert__icon {
59 | font-size: 16px;
60 | width: 16px;
61 | }
62 | .el-alert__icon.is-big {
63 | font-size: 28px;
64 | width: 28px;
65 | }
66 | .el-alert__title {
67 | font-size: 13px;
68 | line-height: 18px;
69 | }
70 | .el-alert__title.is-bold {
71 | font-weight: 700;
72 | }
73 | .el-alert .el-alert__description {
74 | font-size: 12px;
75 | margin: 5px 0 0;
76 | }
77 | .el-alert__closebtn {
78 | font-size: 12px;
79 | color: #c0c4cc;
80 | opacity: 1;
81 | position: absolute;
82 | top: 12px;
83 | right: 15px;
84 | cursor: pointer;
85 | }
86 | .el-alert__closebtn.is-customed {
87 | font-style: normal;
88 | font-size: 13px;
89 | top: 9px;
90 | }
91 | .el-alert-fade-enter,
92 | .el-alert-fade-leave-active {
93 | opacity: 0;
94 | }
95 |
--------------------------------------------------------------------------------
/src/assets/styles/element/aside.css:
--------------------------------------------------------------------------------
1 | .el-aside {
2 | overflow: auto;
3 | -webkit-box-sizing: border-box;
4 | box-sizing: border-box;
5 | -ms-flex-negative: 0;
6 | flex-shrink: 0;
7 | }
8 |
--------------------------------------------------------------------------------
/src/assets/styles/element/badge.css:
--------------------------------------------------------------------------------
1 | .el-badge {
2 | position: relative;
3 | vertical-align: middle;
4 | display: inline-block;
5 | }
6 | .el-badge__content {
7 | background-color: #f56c6c;
8 | border-radius: 10px;
9 | color: #fff;
10 | display: inline-block;
11 | font-size: 12px;
12 | height: 18px;
13 | line-height: 18px;
14 | padding: 0 6px;
15 | text-align: center;
16 | white-space: nowrap;
17 | border: 1px solid #fff;
18 | }
19 | .el-badge__content.is-fixed {
20 | position: absolute;
21 | top: 0;
22 | right: 10px;
23 | -webkit-transform: translateY(-50%) translateX(100%);
24 | transform: translateY(-50%) translateX(100%);
25 | }
26 | .el-badge__content.is-fixed.is-dot {
27 | right: 5px;
28 | }
29 | .el-badge__content.is-dot {
30 | height: 8px;
31 | width: 8px;
32 | padding: 0;
33 | right: 0;
34 | border-radius: 50%;
35 | }
36 |
--------------------------------------------------------------------------------
/src/assets/styles/element/breadcrumb-item.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/src/assets/styles/element/breadcrumb-item.css
--------------------------------------------------------------------------------
/src/assets/styles/element/breadcrumb.css:
--------------------------------------------------------------------------------
1 | .el-breadcrumb {
2 | font-size: 14px;
3 | line-height: 1;
4 | }
5 | .el-breadcrumb::after,
6 | .el-breadcrumb::before {
7 | display: table;
8 | content: '';
9 | }
10 | .el-breadcrumb::after {
11 | clear: both;
12 | }
13 | .el-breadcrumb__separator {
14 | margin: 0 9px;
15 | font-weight: 700;
16 | color: #c0c4cc;
17 | }
18 | .el-breadcrumb__separator[class*='icon'] {
19 | margin: 0 6px;
20 | font-weight: 400;
21 | }
22 | .el-breadcrumb__item {
23 | float: left;
24 | }
25 | .el-breadcrumb__inner {
26 | color: #606266;
27 | }
28 | .el-breadcrumb__inner a,
29 | .el-breadcrumb__inner.is-link {
30 | font-weight: 700;
31 | text-decoration: none;
32 | -webkit-transition: color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
33 | transition: color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
34 | color: #303133;
35 | }
36 | .el-breadcrumb__inner a:hover,
37 | .el-breadcrumb__inner.is-link:hover {
38 | color: #000000;
39 | cursor: pointer;
40 | }
41 | .el-breadcrumb__item:last-child .el-breadcrumb__inner,
42 | .el-breadcrumb__item:last-child .el-breadcrumb__inner a,
43 | .el-breadcrumb__item:last-child .el-breadcrumb__inner a:hover,
44 | .el-breadcrumb__item:last-child .el-breadcrumb__inner:hover {
45 | font-weight: 400;
46 | color: #606266;
47 | cursor: text;
48 | }
49 | .el-breadcrumb__item:last-child .el-breadcrumb__separator {
50 | display: none;
51 | }
52 |
--------------------------------------------------------------------------------
/src/assets/styles/element/button-group.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/src/assets/styles/element/button-group.css
--------------------------------------------------------------------------------
/src/assets/styles/element/card.css:
--------------------------------------------------------------------------------
1 | .el-card {
2 | border-radius: 4px;
3 | border: 1px solid #ebeef5;
4 | background-color: #fff;
5 | overflow: hidden;
6 | color: #303133;
7 | -webkit-transition: 0.3s;
8 | transition: 0.3s;
9 | }
10 | .el-card.is-always-shadow,
11 | .el-card.is-hover-shadow:focus,
12 | .el-card.is-hover-shadow:hover {
13 | -webkit-box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
14 | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
15 | }
16 | .el-card__header {
17 | padding: 18px 20px;
18 | border-bottom: 1px solid #ebeef5;
19 | -webkit-box-sizing: border-box;
20 | box-sizing: border-box;
21 | }
22 | .el-card__body {
23 | padding: 20px;
24 | }
25 |
--------------------------------------------------------------------------------
/src/assets/styles/element/carousel-item.css:
--------------------------------------------------------------------------------
1 | .el-carousel__item,
2 | .el-carousel__mask {
3 | position: absolute;
4 | height: 100%;
5 | top: 0;
6 | left: 0;
7 | }
8 | .el-carousel__item {
9 | width: 100%;
10 | display: inline-block;
11 | overflow: hidden;
12 | z-index: 0;
13 | }
14 | .el-carousel__item.is-active {
15 | z-index: 2;
16 | }
17 | .el-carousel__item.is-animating {
18 | -webkit-transition: -webkit-transform 0.4s ease-in-out;
19 | transition: -webkit-transform 0.4s ease-in-out;
20 | transition: transform 0.4s ease-in-out;
21 | transition: transform 0.4s ease-in-out, -webkit-transform 0.4s ease-in-out;
22 | }
23 | .el-carousel__item--card {
24 | width: 50%;
25 | -webkit-transition: -webkit-transform 0.4s ease-in-out;
26 | transition: -webkit-transform 0.4s ease-in-out;
27 | transition: transform 0.4s ease-in-out;
28 | transition: transform 0.4s ease-in-out, -webkit-transform 0.4s ease-in-out;
29 | }
30 | .el-carousel__item--card.is-in-stage {
31 | cursor: pointer;
32 | z-index: 1;
33 | }
34 | .el-carousel__item--card.is-in-stage.is-hover .el-carousel__mask,
35 | .el-carousel__item--card.is-in-stage:hover .el-carousel__mask {
36 | opacity: 0.12;
37 | }
38 | .el-carousel__item--card.is-active {
39 | z-index: 2;
40 | }
41 | .el-carousel__mask {
42 | width: 100%;
43 | background-color: #fff;
44 | opacity: 0.24;
45 | -webkit-transition: 0.2s;
46 | transition: 0.2s;
47 | }
48 |
--------------------------------------------------------------------------------
/src/assets/styles/element/carousel.css:
--------------------------------------------------------------------------------
1 | .el-carousel {
2 | overflow-x: hidden;
3 | position: relative;
4 | }
5 | .el-carousel__container {
6 | position: relative;
7 | height: 300px;
8 | }
9 | .el-carousel__arrow {
10 | border: none;
11 | outline: 0;
12 | padding: 0;
13 | margin: 0;
14 | height: 36px;
15 | width: 36px;
16 | cursor: pointer;
17 | -webkit-transition: 0.3s;
18 | transition: 0.3s;
19 | border-radius: 50%;
20 | background-color: rgba(31, 45, 61, 0.11);
21 | color: #fff;
22 | position: absolute;
23 | top: 50%;
24 | z-index: 10;
25 | -webkit-transform: translateY(-50%);
26 | transform: translateY(-50%);
27 | text-align: center;
28 | font-size: 12px;
29 | }
30 | .el-carousel__arrow--left {
31 | left: 16px;
32 | }
33 | .el-carousel__arrow--right {
34 | right: 16px;
35 | }
36 | .el-carousel__arrow:hover {
37 | background-color: rgba(31, 45, 61, 0.23);
38 | }
39 | .el-carousel__arrow i {
40 | cursor: pointer;
41 | }
42 | .el-carousel__indicators {
43 | position: absolute;
44 | list-style: none;
45 | bottom: 0;
46 | left: 50%;
47 | -webkit-transform: translateX(-50%);
48 | transform: translateX(-50%);
49 | margin: 0;
50 | padding: 0;
51 | z-index: 2;
52 | }
53 | .el-carousel__indicators--outside {
54 | bottom: 26px;
55 | text-align: center;
56 | position: static;
57 | -webkit-transform: none;
58 | transform: none;
59 | }
60 | .el-carousel__indicators--outside .el-carousel__indicator:hover button {
61 | opacity: 0.64;
62 | }
63 | .el-carousel__indicators--outside button {
64 | background-color: #c0c4cc;
65 | opacity: 0.24;
66 | }
67 | .el-carousel__indicators--labels {
68 | left: 0;
69 | right: 0;
70 | -webkit-transform: none;
71 | transform: none;
72 | text-align: center;
73 | }
74 | .el-carousel__indicators--labels .el-carousel__button {
75 | height: auto;
76 | width: auto;
77 | padding: 2px 18px;
78 | font-size: 12px;
79 | }
80 | .el-carousel__indicators--labels .el-carousel__indicator {
81 | padding: 6px 4px;
82 | }
83 | .el-carousel__indicator {
84 | display: inline-block;
85 | background-color: transparent;
86 | padding: 12px 4px;
87 | cursor: pointer;
88 | }
89 | .el-carousel__indicator:hover button {
90 | opacity: 0.72;
91 | }
92 | .el-carousel__indicator.is-active button {
93 | opacity: 1;
94 | }
95 | .el-carousel__button {
96 | display: block;
97 | opacity: 0.48;
98 | width: 30px;
99 | height: 2px;
100 | background-color: #fff;
101 | border: none;
102 | outline: 0;
103 | padding: 0;
104 | margin: 0;
105 | cursor: pointer;
106 | -webkit-transition: 0.3s;
107 | transition: 0.3s;
108 | }
109 | .carousel-arrow-left-enter,
110 | .carousel-arrow-left-leave-active {
111 | -webkit-transform: translateY(-50%) translateX(-10px);
112 | transform: translateY(-50%) translateX(-10px);
113 | opacity: 0;
114 | }
115 | .carousel-arrow-right-enter,
116 | .carousel-arrow-right-leave-active {
117 | -webkit-transform: translateY(-50%) translateX(10px);
118 | transform: translateY(-50%) translateX(10px);
119 | opacity: 0;
120 | }
121 |
--------------------------------------------------------------------------------
/src/assets/styles/element/checkbox-button.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/src/assets/styles/element/checkbox-button.css
--------------------------------------------------------------------------------
/src/assets/styles/element/checkbox-group.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/src/assets/styles/element/checkbox-group.css
--------------------------------------------------------------------------------
/src/assets/styles/element/collapse-item.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/src/assets/styles/element/collapse-item.css
--------------------------------------------------------------------------------
/src/assets/styles/element/collapse.css:
--------------------------------------------------------------------------------
1 | .el-collapse {
2 | border-top: 1px solid #ebeef5;
3 | border-bottom: 1px solid #ebeef5;
4 | }
5 | .el-collapse-item__header {
6 | height: 48px;
7 | line-height: 48px;
8 | background-color: #fff;
9 | color: #303133;
10 | cursor: pointer;
11 | border-bottom: 1px solid #ebeef5;
12 | font-size: 13px;
13 | font-weight: 500;
14 | -webkit-transition: border-bottom-color 0.3s;
15 | transition: border-bottom-color 0.3s;
16 | outline: 0;
17 | }
18 | .el-collapse-item__arrow {
19 | margin-right: 8px;
20 | -webkit-transition: -webkit-transform 0.3s;
21 | transition: -webkit-transform 0.3s;
22 | transition: transform 0.3s;
23 | transition: transform 0.3s, -webkit-transform 0.3s;
24 | float: right;
25 | line-height: 48px;
26 | font-weight: 300;
27 | }
28 | .el-collapse-item__arrow.is-active {
29 | -webkit-transform: rotate(90deg);
30 | transform: rotate(90deg);
31 | }
32 | .el-collapse-item__header.focusing:focus:not(:hover) {
33 | color: #000000;
34 | }
35 | .el-collapse-item__header.is-active {
36 | border-bottom-color: transparent;
37 | }
38 | .el-collapse-item__wrap {
39 | will-change: height;
40 | background-color: #fff;
41 | overflow: hidden;
42 | -webkit-box-sizing: border-box;
43 | box-sizing: border-box;
44 | border-bottom: 1px solid #ebeef5;
45 | }
46 | .el-collapse-item__content {
47 | padding-bottom: 25px;
48 | font-size: 13px;
49 | color: #303133;
50 | line-height: 1.769230769230769;
51 | }
52 | .el-collapse-item:last-child {
53 | margin-bottom: -1px;
54 | }
55 |
--------------------------------------------------------------------------------
/src/assets/styles/element/container.css:
--------------------------------------------------------------------------------
1 | .el-container {
2 | display: -webkit-box;
3 | display: -ms-flexbox;
4 | display: flex;
5 | -webkit-box-orient: horizontal;
6 | -webkit-box-direction: normal;
7 | -ms-flex-direction: row;
8 | flex-direction: row;
9 | -webkit-box-flex: 1;
10 | -ms-flex: 1;
11 | flex: 1;
12 | -ms-flex-preferred-size: auto;
13 | flex-basis: auto;
14 | -webkit-box-sizing: border-box;
15 | box-sizing: border-box;
16 | min-width: 0;
17 | }
18 | .el-container.is-vertical {
19 | -webkit-box-orient: vertical;
20 | -webkit-box-direction: normal;
21 | -ms-flex-direction: column;
22 | flex-direction: column;
23 | }
24 |
--------------------------------------------------------------------------------
/src/assets/styles/element/dialog.css:
--------------------------------------------------------------------------------
1 | .v-modal-enter {
2 | -webkit-animation: v-modal-in 0.2s ease;
3 | animation: v-modal-in 0.2s ease;
4 | }
5 | .v-modal-leave {
6 | -webkit-animation: v-modal-out 0.2s ease forwards;
7 | animation: v-modal-out 0.2s ease forwards;
8 | }
9 | @-webkit-keyframes v-modal-in {
10 | 0% {
11 | opacity: 0;
12 | }
13 | }
14 | @keyframes v-modal-in {
15 | 0% {
16 | opacity: 0;
17 | }
18 | }
19 | @-webkit-keyframes v-modal-out {
20 | 100% {
21 | opacity: 0;
22 | }
23 | }
24 | @keyframes v-modal-out {
25 | 100% {
26 | opacity: 0;
27 | }
28 | }
29 | .v-modal {
30 | position: fixed;
31 | left: 0;
32 | top: 0;
33 | width: 100%;
34 | height: 100%;
35 | opacity: 0.5;
36 | background: #000;
37 | }
38 | .el-popup-parent--hidden {
39 | overflow: hidden;
40 | }
41 | .el-dialog {
42 | position: relative;
43 | margin: 0 auto 50px;
44 | background: #fff;
45 | border-radius: 2px;
46 | -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
47 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
48 | -webkit-box-sizing: border-box;
49 | box-sizing: border-box;
50 | width: 50%;
51 | }
52 | .el-dialog.is-fullscreen {
53 | width: 100%;
54 | margin-top: 0;
55 | margin-bottom: 0;
56 | height: 100%;
57 | overflow: auto;
58 | }
59 | .el-dialog__wrapper {
60 | position: fixed;
61 | top: 0;
62 | right: 0;
63 | bottom: 0;
64 | left: 0;
65 | overflow: auto;
66 | margin: 0;
67 | }
68 | .el-dialog__header {
69 | padding: 20px 20px 10px;
70 | }
71 | .el-dialog__headerbtn {
72 | position: absolute;
73 | top: 20px;
74 | right: 20px;
75 | padding: 0;
76 | background: 0 0;
77 | border: none;
78 | outline: 0;
79 | cursor: pointer;
80 | font-size: 16px;
81 | }
82 | .el-dialog__headerbtn .el-dialog__close {
83 | color: #909399;
84 | }
85 | .el-dialog__headerbtn:focus .el-dialog__close,
86 | .el-dialog__headerbtn:hover .el-dialog__close {
87 | color: #000000;
88 | }
89 | .el-dialog__title {
90 | line-height: 24px;
91 | font-size: 18px;
92 | color: #303133;
93 | }
94 | .el-dialog__body {
95 | padding: 30px 20px;
96 | color: #606266;
97 | font-size: 14px;
98 | }
99 | .el-dialog__footer {
100 | padding: 10px 20px 20px;
101 | text-align: right;
102 | -webkit-box-sizing: border-box;
103 | box-sizing: border-box;
104 | }
105 | .el-dialog--center {
106 | text-align: center;
107 | }
108 | .el-dialog--center .el-dialog__body {
109 | text-align: initial;
110 | padding: 25px 25px 30px;
111 | }
112 | .el-dialog--center .el-dialog__footer {
113 | text-align: inherit;
114 | }
115 | .dialog-fade-enter-active {
116 | -webkit-animation: dialog-fade-in 0.3s;
117 | animation: dialog-fade-in 0.3s;
118 | }
119 | .dialog-fade-leave-active {
120 | -webkit-animation: dialog-fade-out 0.3s;
121 | animation: dialog-fade-out 0.3s;
122 | }
123 | @-webkit-keyframes dialog-fade-in {
124 | 0% {
125 | -webkit-transform: translate3d(0, -20px, 0);
126 | transform: translate3d(0, -20px, 0);
127 | opacity: 0;
128 | }
129 | 100% {
130 | -webkit-transform: translate3d(0, 0, 0);
131 | transform: translate3d(0, 0, 0);
132 | opacity: 1;
133 | }
134 | }
135 | @keyframes dialog-fade-in {
136 | 0% {
137 | -webkit-transform: translate3d(0, -20px, 0);
138 | transform: translate3d(0, -20px, 0);
139 | opacity: 0;
140 | }
141 | 100% {
142 | -webkit-transform: translate3d(0, 0, 0);
143 | transform: translate3d(0, 0, 0);
144 | opacity: 1;
145 | }
146 | }
147 | @-webkit-keyframes dialog-fade-out {
148 | 0% {
149 | -webkit-transform: translate3d(0, 0, 0);
150 | transform: translate3d(0, 0, 0);
151 | opacity: 1;
152 | }
153 | 100% {
154 | -webkit-transform: translate3d(0, -20px, 0);
155 | transform: translate3d(0, -20px, 0);
156 | opacity: 0;
157 | }
158 | }
159 | @keyframes dialog-fade-out {
160 | 0% {
161 | -webkit-transform: translate3d(0, 0, 0);
162 | transform: translate3d(0, 0, 0);
163 | opacity: 1;
164 | }
165 | 100% {
166 | -webkit-transform: translate3d(0, -20px, 0);
167 | transform: translate3d(0, -20px, 0);
168 | opacity: 0;
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/src/assets/styles/element/display.css:
--------------------------------------------------------------------------------
1 | @media only screen and (max-width: 767px) {
2 | .hidden-xs-only {
3 | display: none !important;
4 | }
5 | }
6 | @media only screen and (min-width: 768px) {
7 | .hidden-sm-and-up {
8 | display: none !important;
9 | }
10 | }
11 | @media only screen and (min-width: 768px) and (max-width: 991px) {
12 | .hidden-sm-only {
13 | display: none !important;
14 | }
15 | }
16 | @media only screen and (max-width: 991px) {
17 | .hidden-sm-and-down {
18 | display: none !important;
19 | }
20 | }
21 | @media only screen and (min-width: 992px) {
22 | .hidden-md-and-up {
23 | display: none !important;
24 | }
25 | }
26 | @media only screen and (min-width: 992px) and (max-width: 1199px) {
27 | .hidden-md-only {
28 | display: none !important;
29 | }
30 | }
31 | @media only screen and (max-width: 1199px) {
32 | .hidden-md-and-down {
33 | display: none !important;
34 | }
35 | }
36 | @media only screen and (min-width: 1200px) {
37 | .hidden-lg-and-up {
38 | display: none !important;
39 | }
40 | }
41 | @media only screen and (min-width: 1200px) and (max-width: 1919px) {
42 | .hidden-lg-only {
43 | display: none !important;
44 | }
45 | }
46 | @media only screen and (max-width: 1919px) {
47 | .hidden-lg-and-down {
48 | display: none !important;
49 | }
50 | }
51 | @media only screen and (min-width: 1920px) {
52 | .hidden-xl-only {
53 | display: none !important;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/assets/styles/element/dropdown-item.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/src/assets/styles/element/dropdown-item.css
--------------------------------------------------------------------------------
/src/assets/styles/element/dropdown-menu.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/src/assets/styles/element/dropdown-menu.css
--------------------------------------------------------------------------------
/src/assets/styles/element/fonts/element-icons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/src/assets/styles/element/fonts/element-icons.ttf
--------------------------------------------------------------------------------
/src/assets/styles/element/fonts/element-icons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/src/assets/styles/element/fonts/element-icons.woff
--------------------------------------------------------------------------------
/src/assets/styles/element/footer.css:
--------------------------------------------------------------------------------
1 | .el-footer {
2 | padding: 0 20px;
3 | -webkit-box-sizing: border-box;
4 | box-sizing: border-box;
5 | -ms-flex-negative: 0;
6 | flex-shrink: 0;
7 | }
8 |
--------------------------------------------------------------------------------
/src/assets/styles/element/form-item.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/src/assets/styles/element/form-item.css
--------------------------------------------------------------------------------
/src/assets/styles/element/form.css:
--------------------------------------------------------------------------------
1 | .el-form--inline .el-form-item,
2 | .el-form--inline .el-form-item__content {
3 | display: inline-block;
4 | vertical-align: top;
5 | }
6 | .el-form-item::after,
7 | .el-form-item__content::after {
8 | clear: both;
9 | }
10 | .el-form--label-left .el-form-item__label {
11 | text-align: left;
12 | }
13 | .el-form--label-top .el-form-item__label {
14 | float: none;
15 | display: inline-block;
16 | text-align: left;
17 | padding: 0 0 10px;
18 | }
19 | .el-form--inline .el-form-item {
20 | margin-right: 10px;
21 | }
22 | .el-form--inline .el-form-item__label {
23 | float: none;
24 | display: inline-block;
25 | }
26 | .el-form-item__content .el-input-group,
27 | .el-form-item__label {
28 | vertical-align: middle;
29 | }
30 | .el-form--inline.el-form--label-top .el-form-item__content {
31 | display: block;
32 | }
33 | .el-form-item {
34 | margin-bottom: 22px;
35 | }
36 | .el-form-item::after,
37 | .el-form-item::before {
38 | display: table;
39 | content: '';
40 | }
41 | .el-form-item .el-form-item {
42 | margin-bottom: 0;
43 | }
44 | .el-form-item--mini.el-form-item,
45 | .el-form-item--small.el-form-item {
46 | margin-bottom: 18px;
47 | }
48 | .el-form-item .el-input__validateIcon {
49 | display: none;
50 | }
51 | .el-form-item--medium .el-form-item__content,
52 | .el-form-item--medium .el-form-item__label {
53 | line-height: 36px;
54 | }
55 | .el-form-item--small .el-form-item__content,
56 | .el-form-item--small .el-form-item__label {
57 | line-height: 32px;
58 | }
59 | .el-form-item--small .el-form-item__error {
60 | padding-top: 2px;
61 | }
62 | .el-form-item--mini .el-form-item__content,
63 | .el-form-item--mini .el-form-item__label {
64 | line-height: 28px;
65 | }
66 | .el-form-item--mini .el-form-item__error {
67 | padding-top: 1px;
68 | }
69 | .el-form-item__label {
70 | text-align: right;
71 | float: left;
72 | font-size: 14px;
73 | color: #606266;
74 | line-height: 40px;
75 | padding: 0 12px 0 0;
76 | -webkit-box-sizing: border-box;
77 | box-sizing: border-box;
78 | }
79 | .el-form-item__content {
80 | line-height: 40px;
81 | position: relative;
82 | font-size: 14px;
83 | }
84 | .el-form-item__content::after,
85 | .el-form-item__content::before {
86 | display: table;
87 | content: '';
88 | }
89 | .el-form-item__error {
90 | color: #f56c6c;
91 | font-size: 12px;
92 | line-height: 1;
93 | padding-top: 4px;
94 | position: absolute;
95 | top: 100%;
96 | left: 0;
97 | }
98 | .el-form-item__error--inline {
99 | position: relative;
100 | top: auto;
101 | left: auto;
102 | display: inline-block;
103 | margin-left: 10px;
104 | }
105 | .el-form-item.is-required .el-form-item__label:before {
106 | content: '*';
107 | color: #f56c6c;
108 | margin-right: 4px;
109 | }
110 | .el-form-item.is-error .el-input__inner,
111 | .el-form-item.is-error .el-input__inner:focus,
112 | .el-form-item.is-error .el-textarea__inner,
113 | .el-form-item.is-error .el-textarea__inner:focus {
114 | border-color: #f56c6c;
115 | }
116 | .el-form-item.is-error .el-input-group__append .el-input__inner,
117 | .el-form-item.is-error .el-input-group__prepend .el-input__inner {
118 | border-color: transparent;
119 | }
120 | .el-form-item.is-error .el-input__validateIcon {
121 | color: #f56c6c;
122 | }
123 | .el-form-item.is-success .el-input__inner,
124 | .el-form-item.is-success .el-input__inner:focus,
125 | .el-form-item.is-success .el-textarea__inner,
126 | .el-form-item.is-success .el-textarea__inner:focus {
127 | border-color: #67c23a;
128 | }
129 | .el-form-item.is-success .el-input-group__append .el-input__inner,
130 | .el-form-item.is-success .el-input-group__prepend .el-input__inner {
131 | border-color: transparent;
132 | }
133 | .el-form-item.is-success .el-input__validateIcon {
134 | color: #67c23a;
135 | }
136 | .el-form-item--feedback .el-input__validateIcon {
137 | display: inline-block;
138 | }
139 |
--------------------------------------------------------------------------------
/src/assets/styles/element/header.css:
--------------------------------------------------------------------------------
1 | .el-header {
2 | padding: 0 20px;
3 | -webkit-box-sizing: border-box;
4 | box-sizing: border-box;
5 | -ms-flex-negative: 0;
6 | flex-shrink: 0;
7 | }
8 |
--------------------------------------------------------------------------------
/src/assets/styles/element/icon.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: element-icons;
3 | src: url(fonts/element-icons.woff) format('woff'), url(fonts/element-icons.ttf) format('truetype');
4 | font-weight: 400;
5 | font-style: normal;
6 | }
7 | [class*=' el-icon-'],
8 | [class^='el-icon-'] {
9 | font-family: element-icons !important;
10 | speak: none;
11 | font-style: normal;
12 | font-weight: 400;
13 | font-variant: normal;
14 | text-transform: none;
15 | line-height: 1;
16 | vertical-align: baseline;
17 | display: inline-block;
18 | -webkit-font-smoothing: antialiased;
19 | -moz-osx-font-smoothing: grayscale;
20 | }
21 | .el-icon-info:before {
22 | content: '\e61a';
23 | }
24 | .el-icon-error:before {
25 | content: '\e62c';
26 | }
27 | .el-icon-success:before {
28 | content: '\e62d';
29 | }
30 | .el-icon-warning:before {
31 | content: '\e62e';
32 | }
33 | .el-icon-question:before {
34 | content: '\e634';
35 | }
36 | .el-icon-back:before {
37 | content: '\e606';
38 | }
39 | .el-icon-arrow-left:before {
40 | content: '\e600';
41 | }
42 | .el-icon-arrow-down:before {
43 | content: '\e603';
44 | }
45 | .el-icon-arrow-right:before {
46 | content: '\e604';
47 | }
48 | .el-icon-arrow-up:before {
49 | content: '\e605';
50 | }
51 | .el-icon-caret-left:before {
52 | content: '\e60a';
53 | }
54 | .el-icon-caret-bottom:before {
55 | content: '\e60b';
56 | }
57 | .el-icon-caret-top:before {
58 | content: '\e60c';
59 | }
60 | .el-icon-caret-right:before {
61 | content: '\e60e';
62 | }
63 | .el-icon-d-arrow-left:before {
64 | content: '\e610';
65 | }
66 | .el-icon-d-arrow-right:before {
67 | content: '\e613';
68 | }
69 | .el-icon-minus:before {
70 | content: '\e621';
71 | }
72 | .el-icon-plus:before {
73 | content: '\e62b';
74 | }
75 | .el-icon-remove:before {
76 | content: '\e635';
77 | }
78 | .el-icon-circle-plus:before {
79 | content: '\e601';
80 | }
81 | .el-icon-remove-outline:before {
82 | content: '\e63c';
83 | }
84 | .el-icon-circle-plus-outline:before {
85 | content: '\e602';
86 | }
87 | .el-icon-close:before {
88 | content: '\e60f';
89 | }
90 | .el-icon-check:before {
91 | content: '\e611';
92 | }
93 | .el-icon-circle-close:before {
94 | content: '\e607';
95 | }
96 | .el-icon-circle-check:before {
97 | content: '\e639';
98 | }
99 | .el-icon-circle-close-outline:before {
100 | content: '\e609';
101 | }
102 | .el-icon-circle-check-outline:before {
103 | content: '\e63e';
104 | }
105 | .el-icon-zoom-out:before {
106 | content: '\e645';
107 | }
108 | .el-icon-zoom-in:before {
109 | content: '\e641';
110 | }
111 | .el-icon-d-caret:before {
112 | content: '\e615';
113 | }
114 | .el-icon-sort:before {
115 | content: '\e640';
116 | }
117 | .el-icon-sort-down:before {
118 | content: '\e630';
119 | }
120 | .el-icon-sort-up:before {
121 | content: '\e631';
122 | }
123 | .el-icon-tickets:before {
124 | content: '\e63f';
125 | }
126 | .el-icon-document:before {
127 | content: '\e614';
128 | }
129 | .el-icon-goods:before {
130 | content: '\e618';
131 | }
132 | .el-icon-sold-out:before {
133 | content: '\e63b';
134 | }
135 | .el-icon-news:before {
136 | content: '\e625';
137 | }
138 | .el-icon-message:before {
139 | content: '\e61b';
140 | }
141 | .el-icon-date:before {
142 | content: '\e608';
143 | }
144 | .el-icon-printer:before {
145 | content: '\e62f';
146 | }
147 | .el-icon-time:before {
148 | content: '\e642';
149 | }
150 | .el-icon-bell:before {
151 | content: '\e622';
152 | }
153 | .el-icon-mobile-phone:before {
154 | content: '\e624';
155 | }
156 | .el-icon-service:before {
157 | content: '\e63a';
158 | }
159 | .el-icon-view:before {
160 | content: '\e643';
161 | }
162 | .el-icon-menu:before {
163 | content: '\e620';
164 | }
165 | .el-icon-more:before {
166 | content: '\e646';
167 | }
168 | .el-icon-more-outline:before {
169 | content: '\e626';
170 | }
171 | .el-icon-star-on:before {
172 | content: '\e637';
173 | }
174 | .el-icon-star-off:before {
175 | content: '\e63d';
176 | }
177 | .el-icon-location:before {
178 | content: '\e61d';
179 | }
180 | .el-icon-location-outline:before {
181 | content: '\e61f';
182 | }
183 | .el-icon-phone:before {
184 | content: '\e627';
185 | }
186 | .el-icon-phone-outline:before {
187 | content: '\e628';
188 | }
189 | .el-icon-picture:before {
190 | content: '\e629';
191 | }
192 | .el-icon-picture-outline:before {
193 | content: '\e62a';
194 | }
195 | .el-icon-delete:before {
196 | content: '\e612';
197 | }
198 | .el-icon-search:before {
199 | content: '\e619';
200 | }
201 | .el-icon-edit:before {
202 | content: '\e61c';
203 | }
204 | .el-icon-edit-outline:before {
205 | content: '\e616';
206 | }
207 | .el-icon-rank:before {
208 | content: '\e632';
209 | }
210 | .el-icon-refresh:before {
211 | content: '\e633';
212 | }
213 | .el-icon-share:before {
214 | content: '\e636';
215 | }
216 | .el-icon-setting:before {
217 | content: '\e638';
218 | }
219 | .el-icon-upload:before {
220 | content: '\e60d';
221 | }
222 | .el-icon-upload2:before {
223 | content: '\e644';
224 | }
225 | .el-icon-download:before {
226 | content: '\e617';
227 | }
228 | .el-icon-loading:before {
229 | content: '\e61e';
230 | }
231 | .el-icon-loading {
232 | -webkit-animation: rotating 2s linear infinite;
233 | animation: rotating 2s linear infinite;
234 | }
235 | .el-icon--right {
236 | margin-left: 5px;
237 | }
238 | .el-icon--left {
239 | margin-right: 5px;
240 | }
241 | @-webkit-keyframes rotating {
242 | 0% {
243 | -webkit-transform: rotateZ(0);
244 | transform: rotateZ(0);
245 | }
246 | 100% {
247 | -webkit-transform: rotateZ(360deg);
248 | transform: rotateZ(360deg);
249 | }
250 | }
251 | @keyframes rotating {
252 | 0% {
253 | -webkit-transform: rotateZ(0);
254 | transform: rotateZ(0);
255 | }
256 | 100% {
257 | -webkit-transform: rotateZ(360deg);
258 | transform: rotateZ(360deg);
259 | }
260 | }
261 |
--------------------------------------------------------------------------------
/src/assets/styles/element/loading.css:
--------------------------------------------------------------------------------
1 | .el-loading-parent--relative {
2 | position: relative !important;
3 | }
4 | .el-loading-parent--hidden {
5 | overflow: hidden !important;
6 | }
7 | .el-loading-mask {
8 | position: absolute;
9 | z-index: 2000;
10 | background-color: rgba(255, 255, 255, 0.9);
11 | margin: 0;
12 | top: 0;
13 | right: 0;
14 | bottom: 0;
15 | left: 0;
16 | -webkit-transition: opacity 0.3s;
17 | transition: opacity 0.3s;
18 | }
19 | .el-loading-mask.is-fullscreen {
20 | position: fixed;
21 | }
22 | .el-loading-mask.is-fullscreen .el-loading-spinner {
23 | margin-top: -25px;
24 | }
25 | .el-loading-mask.is-fullscreen .el-loading-spinner .circular {
26 | height: 50px;
27 | width: 50px;
28 | }
29 | .el-loading-spinner {
30 | top: 50%;
31 | margin-top: -21px;
32 | width: 100%;
33 | text-align: center;
34 | position: absolute;
35 | }
36 | .el-loading-spinner .el-loading-text {
37 | color: #000000;
38 | margin: 3px 0;
39 | font-size: 14px;
40 | }
41 | .el-loading-spinner .circular {
42 | height: 42px;
43 | width: 42px;
44 | -webkit-animation: loading-rotate 2s linear infinite;
45 | animation: loading-rotate 2s linear infinite;
46 | }
47 | .el-loading-spinner .path {
48 | -webkit-animation: loading-dash 1.5s ease-in-out infinite;
49 | animation: loading-dash 1.5s ease-in-out infinite;
50 | stroke-dasharray: 90, 150;
51 | stroke-dashoffset: 0;
52 | stroke-width: 2;
53 | stroke: #000000;
54 | stroke-linecap: round;
55 | }
56 | .el-loading-spinner i {
57 | color: #000000;
58 | }
59 | .el-loading-fade-enter,
60 | .el-loading-fade-leave-active {
61 | opacity: 0;
62 | }
63 | @-webkit-keyframes loading-rotate {
64 | 100% {
65 | -webkit-transform: rotate(360deg);
66 | transform: rotate(360deg);
67 | }
68 | }
69 | @keyframes loading-rotate {
70 | 100% {
71 | -webkit-transform: rotate(360deg);
72 | transform: rotate(360deg);
73 | }
74 | }
75 | @-webkit-keyframes loading-dash {
76 | 0% {
77 | stroke-dasharray: 1, 200;
78 | stroke-dashoffset: 0;
79 | }
80 | 50% {
81 | stroke-dasharray: 90, 150;
82 | stroke-dashoffset: -40px;
83 | }
84 | 100% {
85 | stroke-dasharray: 90, 150;
86 | stroke-dashoffset: -120px;
87 | }
88 | }
89 | @keyframes loading-dash {
90 | 0% {
91 | stroke-dasharray: 1, 200;
92 | stroke-dashoffset: 0;
93 | }
94 | 50% {
95 | stroke-dasharray: 90, 150;
96 | stroke-dashoffset: -40px;
97 | }
98 | 100% {
99 | stroke-dasharray: 90, 150;
100 | stroke-dashoffset: -120px;
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/assets/styles/element/main.css:
--------------------------------------------------------------------------------
1 | .el-main {
2 | -webkit-box-flex: 1;
3 | -ms-flex: 1;
4 | flex: 1;
5 | -ms-flex-preferred-size: auto;
6 | flex-basis: auto;
7 | overflow: auto;
8 | -webkit-box-sizing: border-box;
9 | box-sizing: border-box;
10 | padding: 20px;
11 | }
12 |
--------------------------------------------------------------------------------
/src/assets/styles/element/menu-item-group.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/src/assets/styles/element/menu-item-group.css
--------------------------------------------------------------------------------
/src/assets/styles/element/menu-item.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/src/assets/styles/element/menu-item.css
--------------------------------------------------------------------------------
/src/assets/styles/element/message.css:
--------------------------------------------------------------------------------
1 | .el-message__closeBtn:focus,
2 | .el-message__content:focus {
3 | outline-width: 0;
4 | }
5 | .el-message {
6 | min-width: 380px;
7 | -webkit-box-sizing: border-box;
8 | box-sizing: border-box;
9 | border-radius: 4px;
10 | border-width: 1px;
11 | border-style: solid;
12 | border-color: #ebeef5;
13 | position: fixed;
14 | left: 50%;
15 | top: 20px;
16 | -webkit-transform: translateX(-50%);
17 | transform: translateX(-50%);
18 | background-color: #edf2fc;
19 | -webkit-transition: opacity 0.3s, -webkit-transform 0.4s;
20 | transition: opacity 0.3s, -webkit-transform 0.4s;
21 | transition: opacity 0.3s, transform 0.4s;
22 | transition: opacity 0.3s, transform 0.4s, -webkit-transform 0.4s;
23 | overflow: hidden;
24 | padding: 15px 15px 15px 20px;
25 | display: -webkit-box;
26 | display: -ms-flexbox;
27 | display: flex;
28 | -webkit-box-align: center;
29 | -ms-flex-align: center;
30 | align-items: center;
31 | }
32 | .el-message.is-center {
33 | -webkit-box-pack: center;
34 | -ms-flex-pack: center;
35 | justify-content: center;
36 | }
37 | .el-message.is-closable .el-message__content {
38 | padding-right: 16px;
39 | }
40 | .el-message p {
41 | margin: 0;
42 | }
43 | .el-message--info .el-message__content {
44 | color: #909399;
45 | }
46 | .el-message--success {
47 | background-color: #f0f9eb;
48 | border-color: #e1f3d8;
49 | }
50 | .el-message--success .el-message__content {
51 | color: #67c23a;
52 | }
53 | .el-message--warning {
54 | background-color: #fdf6ec;
55 | border-color: #faecd8;
56 | }
57 | .el-message--warning .el-message__content {
58 | color: #e6a23c;
59 | }
60 | .el-message--error {
61 | background-color: #fef0f0;
62 | border-color: #fde2e2;
63 | }
64 | .el-message--error .el-message__content {
65 | color: #f56c6c;
66 | }
67 | .el-message__icon {
68 | margin-right: 10px;
69 | }
70 | .el-message__content {
71 | padding: 0;
72 | font-size: 14px;
73 | line-height: 1;
74 | }
75 | .el-message__closeBtn {
76 | position: absolute;
77 | top: 50%;
78 | right: 15px;
79 | -webkit-transform: translateY(-50%);
80 | transform: translateY(-50%);
81 | cursor: pointer;
82 | color: #c0c4cc;
83 | font-size: 16px;
84 | }
85 | .el-message__closeBtn:hover {
86 | color: #909399;
87 | }
88 | .el-message .el-icon-success {
89 | color: #67c23a;
90 | }
91 | .el-message .el-icon-error {
92 | color: #f56c6c;
93 | }
94 | .el-message .el-icon-info {
95 | color: #909399;
96 | }
97 | .el-message .el-icon-warning {
98 | color: #e6a23c;
99 | }
100 | .el-message-fade-enter,
101 | .el-message-fade-leave-active {
102 | opacity: 0;
103 | -webkit-transform: translate(-50%, -100%);
104 | transform: translate(-50%, -100%);
105 | }
106 |
--------------------------------------------------------------------------------
/src/assets/styles/element/notification.css:
--------------------------------------------------------------------------------
1 | .el-notification {
2 | display: -webkit-box;
3 | display: -ms-flexbox;
4 | display: flex;
5 | width: 330px;
6 | padding: 14px 26px 14px 13px;
7 | border-radius: 8px;
8 | -webkit-box-sizing: border-box;
9 | box-sizing: border-box;
10 | border: 1px solid #ebeef5;
11 | position: fixed;
12 | background-color: #fff;
13 | -webkit-box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
14 | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
15 | -webkit-transition: opacity 0.3s, left 0.3s, right 0.3s, top 0.4s, bottom 0.3s,
16 | -webkit-transform 0.3s;
17 | transition: opacity 0.3s, left 0.3s, right 0.3s, top 0.4s, bottom 0.3s, -webkit-transform 0.3s;
18 | transition: opacity 0.3s, transform 0.3s, left 0.3s, right 0.3s, top 0.4s, bottom 0.3s;
19 | transition: opacity 0.3s, transform 0.3s, left 0.3s, right 0.3s, top 0.4s, bottom 0.3s,
20 | -webkit-transform 0.3s;
21 | overflow: hidden;
22 | }
23 | .el-notification.right {
24 | right: 16px;
25 | }
26 | .el-notification.left {
27 | left: 16px;
28 | }
29 | .el-notification__group {
30 | margin-left: 13px;
31 | }
32 | .el-notification__title {
33 | font-weight: 700;
34 | font-size: 16px;
35 | color: #303133;
36 | margin: 0;
37 | }
38 | .el-notification__content {
39 | font-size: 14px;
40 | line-height: 21px;
41 | margin: 6px 0 0;
42 | color: #606266;
43 | text-align: justify;
44 | }
45 | .el-notification__content p {
46 | margin: 0;
47 | }
48 | .el-notification__icon {
49 | height: 24px;
50 | width: 24px;
51 | font-size: 24px;
52 | }
53 | .el-notification__closeBtn {
54 | position: absolute;
55 | top: 18px;
56 | right: 15px;
57 | cursor: pointer;
58 | color: #909399;
59 | font-size: 16px;
60 | }
61 | .el-notification__closeBtn:hover {
62 | color: #606266;
63 | }
64 | .el-notification .el-icon-success {
65 | color: #67c23a;
66 | }
67 | .el-notification .el-icon-error {
68 | color: #f56c6c;
69 | }
70 | .el-notification .el-icon-info {
71 | color: #909399;
72 | }
73 | .el-notification .el-icon-warning {
74 | color: #e6a23c;
75 | }
76 | .el-notification-fade-enter.right {
77 | right: 0;
78 | -webkit-transform: translateX(100%);
79 | transform: translateX(100%);
80 | }
81 | .el-notification-fade-enter.left {
82 | left: 0;
83 | -webkit-transform: translateX(-100%);
84 | transform: translateX(-100%);
85 | }
86 | .el-notification-fade-leave-active {
87 | opacity: 0;
88 | }
89 |
--------------------------------------------------------------------------------
/src/assets/styles/element/option-group.css:
--------------------------------------------------------------------------------
1 | .el-select-group {
2 | margin: 0;
3 | padding: 0;
4 | }
5 | .el-select-group__wrap {
6 | position: relative;
7 | list-style: none;
8 | margin: 0;
9 | padding: 0;
10 | }
11 | .el-select-group__wrap:not(:last-of-type) {
12 | padding-bottom: 24px;
13 | }
14 | .el-select-group__wrap:not(:last-of-type)::after {
15 | content: '';
16 | position: absolute;
17 | display: block;
18 | left: 20px;
19 | right: 20px;
20 | bottom: 12px;
21 | height: 1px;
22 | background: #e4e7ed;
23 | }
24 | .el-select-group__title {
25 | padding-left: 20px;
26 | font-size: 12px;
27 | color: #909399;
28 | line-height: 30px;
29 | }
30 | .el-select-group .el-select-dropdown__item {
31 | padding-left: 20px;
32 | }
33 |
--------------------------------------------------------------------------------
/src/assets/styles/element/option.css:
--------------------------------------------------------------------------------
1 | .el-select-dropdown__item {
2 | font-size: 14px;
3 | padding: 0 20px;
4 | position: relative;
5 | white-space: nowrap;
6 | overflow: hidden;
7 | text-overflow: ellipsis;
8 | color: #606266;
9 | height: 34px;
10 | line-height: 34px;
11 | -webkit-box-sizing: border-box;
12 | box-sizing: border-box;
13 | cursor: pointer;
14 | }
15 | .el-select-dropdown__item.is-disabled {
16 | color: #c0c4cc;
17 | cursor: not-allowed;
18 | }
19 | .el-select-dropdown__item.is-disabled:hover {
20 | background-color: #fff;
21 | }
22 | .el-select-dropdown__item.hover,
23 | .el-select-dropdown__item:hover {
24 | background-color: #f5f7fa;
25 | }
26 | .el-select-dropdown__item.selected {
27 | color: #000000;
28 | font-weight: 700;
29 | }
30 | .el-select-dropdown__item span {
31 | line-height: 34px !important;
32 | }
33 |
--------------------------------------------------------------------------------
/src/assets/styles/element/popover.css:
--------------------------------------------------------------------------------
1 | .el-popper .popper__arrow,
2 | .el-popper .popper__arrow::after {
3 | position: absolute;
4 | display: block;
5 | width: 0;
6 | height: 0;
7 | border-color: transparent;
8 | border-style: solid;
9 | }
10 | .el-popper .popper__arrow {
11 | border-width: 6px;
12 | -webkit-filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
13 | filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
14 | }
15 | .el-popper .popper__arrow::after {
16 | content: ' ';
17 | border-width: 6px;
18 | }
19 | .el-popper[x-placement^='top'] {
20 | margin-bottom: 12px;
21 | }
22 | .el-popper[x-placement^='top'] .popper__arrow {
23 | bottom: -6px;
24 | left: 50%;
25 | margin-right: 3px;
26 | border-top-color: #ebeef5;
27 | border-bottom-width: 0;
28 | }
29 | .el-popper[x-placement^='top'] .popper__arrow::after {
30 | bottom: 1px;
31 | margin-left: -6px;
32 | border-top-color: #fff;
33 | border-bottom-width: 0;
34 | }
35 | .el-popper[x-placement^='bottom'] {
36 | margin-top: 12px;
37 | }
38 | .el-popper[x-placement^='bottom'] .popper__arrow {
39 | top: -6px;
40 | left: 50%;
41 | margin-right: 3px;
42 | border-top-width: 0;
43 | border-bottom-color: #ebeef5;
44 | }
45 | .el-popper[x-placement^='bottom'] .popper__arrow::after {
46 | top: 1px;
47 | margin-left: -6px;
48 | border-top-width: 0;
49 | border-bottom-color: #fff;
50 | }
51 | .el-popper[x-placement^='right'] {
52 | margin-left: 12px;
53 | }
54 | .el-popper[x-placement^='right'] .popper__arrow {
55 | top: 50%;
56 | left: -6px;
57 | margin-bottom: 3px;
58 | border-right-color: #ebeef5;
59 | border-left-width: 0;
60 | }
61 | .el-popper[x-placement^='right'] .popper__arrow::after {
62 | bottom: -6px;
63 | left: 1px;
64 | border-right-color: #fff;
65 | border-left-width: 0;
66 | }
67 | .el-popper[x-placement^='left'] {
68 | margin-right: 12px;
69 | }
70 | .el-popper[x-placement^='left'] .popper__arrow {
71 | top: 50%;
72 | right: -6px;
73 | margin-bottom: 3px;
74 | border-right-width: 0;
75 | border-left-color: #ebeef5;
76 | }
77 | .el-popper[x-placement^='left'] .popper__arrow::after {
78 | right: 1px;
79 | bottom: -6px;
80 | margin-left: -6px;
81 | border-right-width: 0;
82 | border-left-color: #fff;
83 | }
84 | .el-popover {
85 | position: absolute;
86 | background: #fff;
87 | min-width: 150px;
88 | border-radius: 4px;
89 | border: 1px solid #ebeef5;
90 | padding: 12px;
91 | z-index: 2000;
92 | color: #606266;
93 | line-height: 1.4;
94 | text-align: justify;
95 | font-size: 14px;
96 | -webkit-box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
97 | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
98 | }
99 | .el-popover--plain {
100 | padding: 18px 20px;
101 | }
102 | .el-popover__title {
103 | color: #303133;
104 | font-size: 16px;
105 | line-height: 1;
106 | margin-bottom: 12px;
107 | }
108 | .el-popover:focus,
109 | .el-popover:focus:active,
110 | .el-popover__reference:focus:hover,
111 | .el-popover__reference:focus:not(.focusing) {
112 | outline-width: 0;
113 | }
114 |
--------------------------------------------------------------------------------
/src/assets/styles/element/popper.css:
--------------------------------------------------------------------------------
1 | .el-popper .popper__arrow,
2 | .el-popper .popper__arrow::after {
3 | position: absolute;
4 | display: block;
5 | width: 0;
6 | height: 0;
7 | border-color: transparent;
8 | border-style: solid;
9 | }
10 | .el-popper .popper__arrow {
11 | border-width: 6px;
12 | -webkit-filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
13 | filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
14 | }
15 | .el-popper .popper__arrow::after {
16 | content: ' ';
17 | border-width: 6px;
18 | }
19 | .el-popper[x-placement^='top'] {
20 | margin-bottom: 12px;
21 | }
22 | .el-popper[x-placement^='top'] .popper__arrow {
23 | bottom: -6px;
24 | left: 50%;
25 | margin-right: 3px;
26 | border-top-color: #ebeef5;
27 | border-bottom-width: 0;
28 | }
29 | .el-popper[x-placement^='top'] .popper__arrow::after {
30 | bottom: 1px;
31 | margin-left: -6px;
32 | border-top-color: #fff;
33 | border-bottom-width: 0;
34 | }
35 | .el-popper[x-placement^='bottom'] {
36 | margin-top: 12px;
37 | }
38 | .el-popper[x-placement^='bottom'] .popper__arrow {
39 | top: -6px;
40 | left: 50%;
41 | margin-right: 3px;
42 | border-top-width: 0;
43 | border-bottom-color: #ebeef5;
44 | }
45 | .el-popper[x-placement^='bottom'] .popper__arrow::after {
46 | top: 1px;
47 | margin-left: -6px;
48 | border-top-width: 0;
49 | border-bottom-color: #fff;
50 | }
51 | .el-popper[x-placement^='right'] {
52 | margin-left: 12px;
53 | }
54 | .el-popper[x-placement^='right'] .popper__arrow {
55 | top: 50%;
56 | left: -6px;
57 | margin-bottom: 3px;
58 | border-right-color: #ebeef5;
59 | border-left-width: 0;
60 | }
61 | .el-popper[x-placement^='right'] .popper__arrow::after {
62 | bottom: -6px;
63 | left: 1px;
64 | border-right-color: #fff;
65 | border-left-width: 0;
66 | }
67 | .el-popper[x-placement^='left'] {
68 | margin-right: 12px;
69 | }
70 | .el-popper[x-placement^='left'] .popper__arrow {
71 | top: 50%;
72 | right: -6px;
73 | margin-bottom: 3px;
74 | border-right-width: 0;
75 | border-left-color: #ebeef5;
76 | }
77 | .el-popper[x-placement^='left'] .popper__arrow::after {
78 | right: 1px;
79 | bottom: -6px;
80 | margin-left: -6px;
81 | border-right-width: 0;
82 | border-left-color: #fff;
83 | }
84 |
--------------------------------------------------------------------------------
/src/assets/styles/element/progress.css:
--------------------------------------------------------------------------------
1 | .el-progress {
2 | position: relative;
3 | line-height: 1;
4 | }
5 | .el-progress__text {
6 | font-size: 14px;
7 | color: #606266;
8 | display: inline-block;
9 | vertical-align: middle;
10 | margin-left: 10px;
11 | line-height: 1;
12 | }
13 | .el-progress__text i {
14 | vertical-align: middle;
15 | display: block;
16 | }
17 | .el-progress--circle {
18 | display: inline-block;
19 | }
20 | .el-progress--circle .el-progress__text {
21 | position: absolute;
22 | top: 50%;
23 | left: 0;
24 | width: 100%;
25 | text-align: center;
26 | margin: 0;
27 | -webkit-transform: translate(0, -50%);
28 | transform: translate(0, -50%);
29 | }
30 | .el-progress--circle .el-progress__text i {
31 | vertical-align: middle;
32 | display: inline-block;
33 | }
34 | .el-progress--without-text .el-progress__text {
35 | display: none;
36 | }
37 | .el-progress--without-text .el-progress-bar {
38 | padding-right: 0;
39 | margin-right: 0;
40 | display: block;
41 | }
42 | .el-progress-bar,
43 | .el-progress-bar__inner::after,
44 | .el-progress-bar__innerText {
45 | display: inline-block;
46 | vertical-align: middle;
47 | }
48 | .el-progress--text-inside .el-progress-bar {
49 | padding-right: 0;
50 | margin-right: 0;
51 | }
52 | .el-progress.is-success .el-progress-bar__inner {
53 | background-color: #67c23a;
54 | }
55 | .el-progress.is-success .el-progress__text {
56 | color: #67c23a;
57 | }
58 | .el-progress.is-exception .el-progress-bar__inner {
59 | background-color: #f56c6c;
60 | }
61 | .el-progress.is-exception .el-progress__text {
62 | color: #f56c6c;
63 | }
64 | .el-progress-bar {
65 | padding-right: 50px;
66 | width: 100%;
67 | margin-right: -55px;
68 | -webkit-box-sizing: border-box;
69 | box-sizing: border-box;
70 | }
71 | .el-progress-bar__outer {
72 | height: 6px;
73 | border-radius: 100px;
74 | background-color: #ebeef5;
75 | overflow: hidden;
76 | position: relative;
77 | vertical-align: middle;
78 | }
79 | .el-progress-bar__inner {
80 | position: absolute;
81 | left: 0;
82 | top: 0;
83 | height: 100%;
84 | background-color: #000000;
85 | text-align: right;
86 | border-radius: 100px;
87 | line-height: 1;
88 | white-space: nowrap;
89 | }
90 | .el-progress-bar__inner::after {
91 | content: '';
92 | height: 100%;
93 | }
94 | .el-progress-bar__innerText {
95 | color: #fff;
96 | font-size: 12px;
97 | margin: 0 5px;
98 | }
99 | @-webkit-keyframes progress {
100 | 0% {
101 | background-position: 0 0;
102 | }
103 | 100% {
104 | background-position: 32px 0;
105 | }
106 | }
107 | @keyframes progress {
108 | 0% {
109 | background-position: 0 0;
110 | }
111 | 100% {
112 | background-position: 32px 0;
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/src/assets/styles/element/radio-button.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | .el-radio-button,
3 | .el-radio-button__inner {
4 | display: inline-block;
5 | position: relative;
6 | outline: 0;
7 | }
8 | .el-radio-button__inner {
9 | line-height: 1;
10 | white-space: nowrap;
11 | vertical-align: middle;
12 | background: #fff;
13 | border: 1px solid #dcdfe6;
14 | font-weight: 500;
15 | border-left: 0;
16 | color: #606266;
17 | -webkit-appearance: none;
18 | text-align: center;
19 | -webkit-box-sizing: border-box;
20 | box-sizing: border-box;
21 | margin: 0;
22 | cursor: pointer;
23 | -webkit-transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
24 | transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
25 | padding: 12px 20px;
26 | font-size: 14px;
27 | border-radius: 0;
28 | }
29 | .el-radio-button__inner.is-round {
30 | padding: 12px 20px;
31 | }
32 | .el-radio-button__inner:hover {
33 | color: #000000;
34 | }
35 | .el-radio-button__inner [class*='el-icon-'] {
36 | line-height: 0.9;
37 | }
38 | .el-radio-button__inner [class*='el-icon-'] + span {
39 | margin-left: 5px;
40 | }
41 | .el-radio-button:first-child .el-radio-button__inner {
42 | border-left: 1px solid #dcdfe6;
43 | border-radius: 4px 0 0 4px;
44 | -webkit-box-shadow: none !important;
45 | box-shadow: none !important;
46 | }
47 | .el-radio-button__orig-radio {
48 | opacity: 0;
49 | outline: 0;
50 | position: absolute;
51 | z-index: -1;
52 | }
53 | .el-radio-button__orig-radio:checked + .el-radio-button__inner {
54 | color: #fff;
55 | background-color: #000000;
56 | border-color: #000000;
57 | -webkit-box-shadow: -1px 0 0 0 #000000;
58 | box-shadow: -1px 0 0 0 #000000;
59 | }
60 | .el-radio-button__orig-radio:disabled + .el-radio-button__inner {
61 | color: #c0c4cc;
62 | cursor: not-allowed;
63 | background-image: none;
64 | background-color: #fff;
65 | border-color: #ebeef5;
66 | -webkit-box-shadow: none;
67 | box-shadow: none;
68 | }
69 | .el-radio-button__orig-radio:disabled:checked + .el-radio-button__inner {
70 | background-color: #f2f6fc;
71 | }
72 | .el-radio-button:last-child .el-radio-button__inner {
73 | border-radius: 0 4px 4px 0;
74 | }
75 | .el-radio-button:first-child:last-child .el-radio-button__inner {
76 | border-radius: 4px;
77 | }
78 | .el-radio-button--medium .el-radio-button__inner {
79 | padding: 10px 20px;
80 | font-size: 14px;
81 | border-radius: 0;
82 | }
83 | .el-radio-button--medium .el-radio-button__inner.is-round {
84 | padding: 10px 20px;
85 | }
86 | .el-radio-button--small .el-radio-button__inner {
87 | padding: 9px 15px;
88 | font-size: 12px;
89 | border-radius: 0;
90 | }
91 | .el-radio-button--small .el-radio-button__inner.is-round {
92 | padding: 9px 15px;
93 | }
94 | .el-radio-button--mini .el-radio-button__inner {
95 | padding: 7px 15px;
96 | font-size: 12px;
97 | border-radius: 0;
98 | }
99 | .el-radio-button--mini .el-radio-button__inner.is-round {
100 | padding: 7px 15px;
101 | }
102 | .el-radio-button:focus:not(.is-focus):not(:active) {
103 | -webkit-box-shadow: 0 0 2px 2px #000000;
104 | box-shadow: 0 0 2px 2px #000000;
105 | }
106 |
--------------------------------------------------------------------------------
/src/assets/styles/element/radio-group.css:
--------------------------------------------------------------------------------
1 | .el-radio-group {
2 | display: inline-block;
3 | line-height: 1;
4 | vertical-align: middle;
5 | font-size: 0;
6 | }
7 |
--------------------------------------------------------------------------------
/src/assets/styles/element/radio.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | .el-radio,
3 | .el-radio--medium.is-bordered .el-radio__label {
4 | font-size: 14px;
5 | }
6 | .el-radio,
7 | .el-radio__input {
8 | white-space: nowrap;
9 | line-height: 1;
10 | outline: 0;
11 | }
12 | .el-radio,
13 | .el-radio__inner,
14 | .el-radio__input {
15 | position: relative;
16 | display: inline-block;
17 | }
18 | .el-radio {
19 | color: #606266;
20 | font-weight: 500;
21 | cursor: pointer;
22 | -moz-user-select: none;
23 | -webkit-user-select: none;
24 | -ms-user-select: none;
25 | }
26 | .el-radio.is-bordered {
27 | padding: 12px 20px 0 10px;
28 | border-radius: 4px;
29 | border: 1px solid #dcdfe6;
30 | -webkit-box-sizing: border-box;
31 | box-sizing: border-box;
32 | height: 40px;
33 | }
34 | .el-radio.is-bordered.is-checked {
35 | border-color: #000000;
36 | }
37 | .el-radio.is-bordered.is-disabled {
38 | cursor: not-allowed;
39 | border-color: #ebeef5;
40 | }
41 | .el-radio__input.is-disabled .el-radio__inner,
42 | .el-radio__input.is-disabled.is-checked .el-radio__inner {
43 | background-color: #f5f7fa;
44 | border-color: #e4e7ed;
45 | }
46 | .el-radio.is-bordered + .el-radio.is-bordered {
47 | margin-left: 10px;
48 | }
49 | .el-radio--medium.is-bordered {
50 | padding: 10px 20px 0 10px;
51 | border-radius: 4px;
52 | height: 36px;
53 | }
54 | .el-radio--mini.is-bordered .el-radio__label,
55 | .el-radio--small.is-bordered .el-radio__label {
56 | font-size: 12px;
57 | }
58 | .el-radio--medium.is-bordered .el-radio__inner {
59 | height: 14px;
60 | width: 14px;
61 | }
62 | .el-radio--small.is-bordered {
63 | padding: 8px 15px 0 10px;
64 | border-radius: 3px;
65 | height: 32px;
66 | }
67 | .el-radio--small.is-bordered .el-radio__inner {
68 | height: 12px;
69 | width: 12px;
70 | }
71 | .el-radio--mini.is-bordered {
72 | padding: 6px 15px 0 10px;
73 | border-radius: 3px;
74 | height: 28px;
75 | }
76 | .el-radio--mini.is-bordered .el-radio__inner {
77 | height: 12px;
78 | width: 12px;
79 | }
80 | .el-radio + .el-radio {
81 | margin-left: 30px;
82 | }
83 | .el-radio__input {
84 | cursor: pointer;
85 | vertical-align: middle;
86 | }
87 | .el-radio__input.is-disabled .el-radio__inner {
88 | cursor: not-allowed;
89 | }
90 | .el-radio__input.is-disabled .el-radio__inner::after {
91 | cursor: not-allowed;
92 | background-color: #f5f7fa;
93 | }
94 | .el-radio__input.is-disabled .el-radio__inner + .el-radio__label {
95 | cursor: not-allowed;
96 | }
97 | .el-radio__input.is-disabled.is-checked .el-radio__inner::after {
98 | background-color: #c0c4cc;
99 | }
100 | .el-radio__input.is-disabled + span.el-radio__label {
101 | color: #c0c4cc;
102 | cursor: not-allowed;
103 | }
104 | .el-radio__input.is-checked .el-radio__inner {
105 | border-color: #000000;
106 | background: #000000;
107 | }
108 | .el-radio__input.is-checked .el-radio__inner::after {
109 | -webkit-transform: translate(-50%, -50%) scale(1);
110 | transform: translate(-50%, -50%) scale(1);
111 | }
112 | .el-radio__input.is-checked + .el-radio__label {
113 | color: #000000;
114 | }
115 | .el-radio__input.is-focus .el-radio__inner {
116 | border-color: #000000;
117 | }
118 | .el-radio__inner {
119 | border: 1px solid #dcdfe6;
120 | border-radius: 100%;
121 | width: 14px;
122 | height: 14px;
123 | background-color: #fff;
124 | cursor: pointer;
125 | -webkit-box-sizing: border-box;
126 | box-sizing: border-box;
127 | }
128 | .el-radio__inner:hover {
129 | border-color: #000000;
130 | }
131 | .el-radio__inner::after {
132 | width: 4px;
133 | height: 4px;
134 | border-radius: 100%;
135 | background-color: #fff;
136 | content: '';
137 | position: absolute;
138 | left: 50%;
139 | top: 50%;
140 | -webkit-transform: translate(-50%, -50%) scale(0);
141 | transform: translate(-50%, -50%) scale(0);
142 | -webkit-transition: -webkit-transform 0.15s ease-in;
143 | transition: -webkit-transform 0.15s ease-in;
144 | transition: transform 0.15s ease-in;
145 | transition: transform 0.15s ease-in, -webkit-transform 0.15s ease-in;
146 | }
147 | .el-radio__original {
148 | opacity: 0;
149 | outline: 0;
150 | position: absolute;
151 | z-index: -1;
152 | top: 0;
153 | left: 0;
154 | right: 0;
155 | bottom: 0;
156 | margin: 0;
157 | }
158 | .el-radio:focus:not(.is-focus):not(:active) .el-radio__inner {
159 | -webkit-box-shadow: 0 0 2px 2px #000000;
160 | box-shadow: 0 0 2px 2px #000000;
161 | }
162 | .el-radio__label {
163 | font-size: 14px;
164 | padding-left: 10px;
165 | }
166 |
--------------------------------------------------------------------------------
/src/assets/styles/element/rate.css:
--------------------------------------------------------------------------------
1 | .el-rate__icon,
2 | .el-rate__item {
3 | position: relative;
4 | display: inline-block;
5 | }
6 | .el-rate {
7 | height: 20px;
8 | line-height: 1;
9 | }
10 | .el-rate:active,
11 | .el-rate:focus {
12 | outline-width: 0;
13 | }
14 | .el-rate__item {
15 | font-size: 0;
16 | vertical-align: middle;
17 | }
18 | .el-rate__icon {
19 | font-size: 18px;
20 | margin-right: 6px;
21 | color: #c0c4cc;
22 | -webkit-transition: 0.3s;
23 | transition: 0.3s;
24 | }
25 | .el-rate__decimal,
26 | .el-rate__icon .path2 {
27 | position: absolute;
28 | top: 0;
29 | left: 0;
30 | }
31 | .el-rate__icon.hover {
32 | -webkit-transform: scale(1.15);
33 | transform: scale(1.15);
34 | }
35 | .el-rate__decimal {
36 | display: inline-block;
37 | overflow: hidden;
38 | }
39 | .el-rate__text {
40 | font-size: 14px;
41 | vertical-align: middle;
42 | }
43 |
--------------------------------------------------------------------------------
/src/assets/styles/element/reset.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | body {
3 | font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei',
4 | '微软雅黑', Arial, sans-serif;
5 | font-weight: 400;
6 | font-size: 14px;
7 | color: #000;
8 | -webkit-font-smoothing: antialiased;
9 | }
10 | a {
11 | color: #000000;
12 | text-decoration: none;
13 | }
14 | a:focus,
15 | a:hover {
16 | color: rgb(51, 51, 51);
17 | }
18 | a:active {
19 | color: rgb(0, 0, 0);
20 | }
21 | h1,
22 | h2,
23 | h3,
24 | h4,
25 | h5,
26 | h6 {
27 | color: #606266;
28 | font-weight: inherit;
29 | }
30 | h1:first-child,
31 | h2:first-child,
32 | h3:first-child,
33 | h4:first-child,
34 | h5:first-child,
35 | h6:first-child,
36 | p:first-child {
37 | margin-top: 0;
38 | }
39 | h1:last-child,
40 | h2:last-child,
41 | h3:last-child,
42 | h4:last-child,
43 | h5:last-child,
44 | h6:last-child,
45 | p:last-child {
46 | margin-bottom: 0;
47 | }
48 | h1 {
49 | font-size: 20px;
50 | }
51 | h2 {
52 | font-size: 18px;
53 | }
54 | h3 {
55 | font-size: 16px;
56 | }
57 | h4,
58 | h5,
59 | h6,
60 | p {
61 | font-size: inherit;
62 | }
63 | p {
64 | line-height: 1.8;
65 | }
66 | sub,
67 | sup {
68 | font-size: 13px;
69 | }
70 | small {
71 | font-size: 12px;
72 | }
73 | hr {
74 | margin-top: 20px;
75 | margin-bottom: 20px;
76 | border: 0;
77 | border-top: 1px solid #eee;
78 | }
79 |
--------------------------------------------------------------------------------
/src/assets/styles/element/row.css:
--------------------------------------------------------------------------------
1 | .el-row {
2 | position: relative;
3 | -webkit-box-sizing: border-box;
4 | box-sizing: border-box;
5 | }
6 | .el-row::after,
7 | .el-row::before {
8 | display: table;
9 | content: '';
10 | }
11 | .el-row::after {
12 | clear: both;
13 | }
14 | .el-row--flex {
15 | display: -webkit-box;
16 | display: -ms-flexbox;
17 | display: flex;
18 | }
19 | .el-row--flex:after,
20 | .el-row--flex:before {
21 | display: none;
22 | }
23 | .el-row--flex.is-justify-center {
24 | -webkit-box-pack: center;
25 | -ms-flex-pack: center;
26 | justify-content: center;
27 | }
28 | .el-row--flex.is-justify-end {
29 | -webkit-box-pack: end;
30 | -ms-flex-pack: end;
31 | justify-content: flex-end;
32 | }
33 | .el-row--flex.is-justify-space-between {
34 | -webkit-box-pack: justify;
35 | -ms-flex-pack: justify;
36 | justify-content: space-between;
37 | }
38 | .el-row--flex.is-justify-space-around {
39 | -ms-flex-pack: distribute;
40 | justify-content: space-around;
41 | }
42 | .el-row--flex.is-align-middle {
43 | -webkit-box-align: center;
44 | -ms-flex-align: center;
45 | align-items: center;
46 | }
47 | .el-row--flex.is-align-bottom {
48 | -webkit-box-align: end;
49 | -ms-flex-align: end;
50 | align-items: flex-end;
51 | }
52 |
--------------------------------------------------------------------------------
/src/assets/styles/element/scrollbar.css:
--------------------------------------------------------------------------------
1 | .el-scrollbar {
2 | overflow: hidden;
3 | position: relative;
4 | }
5 | .el-scrollbar:active > .el-scrollbar__bar,
6 | .el-scrollbar:focus > .el-scrollbar__bar,
7 | .el-scrollbar:hover > .el-scrollbar__bar {
8 | opacity: 1;
9 | -webkit-transition: opacity 340ms ease-out;
10 | transition: opacity 340ms ease-out;
11 | }
12 | .el-scrollbar__wrap {
13 | overflow: scroll;
14 | height: 100%;
15 | }
16 | .el-scrollbar__wrap--hidden-default::-webkit-scrollbar {
17 | width: 0;
18 | height: 0;
19 | }
20 | .el-scrollbar__thumb {
21 | position: relative;
22 | display: block;
23 | width: 0;
24 | height: 0;
25 | cursor: pointer;
26 | border-radius: inherit;
27 | background-color: rgba(144, 147, 153, 0.3);
28 | -webkit-transition: 0.3s background-color;
29 | transition: 0.3s background-color;
30 | }
31 | .el-scrollbar__thumb:hover {
32 | background-color: rgba(144, 147, 153, 0.5);
33 | }
34 | .el-scrollbar__bar {
35 | position: absolute;
36 | right: 2px;
37 | bottom: 2px;
38 | z-index: 1;
39 | border-radius: 4px;
40 | opacity: 0;
41 | -webkit-transition: opacity 120ms ease-out;
42 | transition: opacity 120ms ease-out;
43 | }
44 | .el-scrollbar__bar.is-vertical {
45 | width: 6px;
46 | top: 2px;
47 | }
48 | .el-scrollbar__bar.is-vertical > div {
49 | width: 100%;
50 | }
51 | .el-scrollbar__bar.is-horizontal {
52 | height: 6px;
53 | left: 2px;
54 | }
55 | .el-scrollbar__bar.is-horizontal > div {
56 | height: 100%;
57 | }
58 |
--------------------------------------------------------------------------------
/src/assets/styles/element/select-dropdown.css:
--------------------------------------------------------------------------------
1 | .el-popper .popper__arrow,
2 | .el-popper .popper__arrow::after {
3 | position: absolute;
4 | display: block;
5 | width: 0;
6 | height: 0;
7 | border-color: transparent;
8 | border-style: solid;
9 | }
10 | .el-popper .popper__arrow {
11 | border-width: 6px;
12 | -webkit-filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
13 | filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
14 | }
15 | .el-popper .popper__arrow::after {
16 | content: ' ';
17 | border-width: 6px;
18 | }
19 | .el-popper[x-placement^='top'] {
20 | margin-bottom: 12px;
21 | }
22 | .el-popper[x-placement^='top'] .popper__arrow {
23 | bottom: -6px;
24 | left: 50%;
25 | margin-right: 3px;
26 | border-top-color: #ebeef5;
27 | border-bottom-width: 0;
28 | }
29 | .el-popper[x-placement^='top'] .popper__arrow::after {
30 | bottom: 1px;
31 | margin-left: -6px;
32 | border-top-color: #fff;
33 | border-bottom-width: 0;
34 | }
35 | .el-popper[x-placement^='bottom'] {
36 | margin-top: 12px;
37 | }
38 | .el-popper[x-placement^='bottom'] .popper__arrow {
39 | top: -6px;
40 | left: 50%;
41 | margin-right: 3px;
42 | border-top-width: 0;
43 | border-bottom-color: #ebeef5;
44 | }
45 | .el-popper[x-placement^='bottom'] .popper__arrow::after {
46 | top: 1px;
47 | margin-left: -6px;
48 | border-top-width: 0;
49 | border-bottom-color: #fff;
50 | }
51 | .el-popper[x-placement^='right'] {
52 | margin-left: 12px;
53 | }
54 | .el-popper[x-placement^='right'] .popper__arrow {
55 | top: 50%;
56 | left: -6px;
57 | margin-bottom: 3px;
58 | border-right-color: #ebeef5;
59 | border-left-width: 0;
60 | }
61 | .el-popper[x-placement^='right'] .popper__arrow::after {
62 | bottom: -6px;
63 | left: 1px;
64 | border-right-color: #fff;
65 | border-left-width: 0;
66 | }
67 | .el-popper[x-placement^='left'] {
68 | margin-right: 12px;
69 | }
70 | .el-popper[x-placement^='left'] .popper__arrow {
71 | top: 50%;
72 | right: -6px;
73 | margin-bottom: 3px;
74 | border-right-width: 0;
75 | border-left-color: #ebeef5;
76 | }
77 | .el-popper[x-placement^='left'] .popper__arrow::after {
78 | right: 1px;
79 | bottom: -6px;
80 | margin-left: -6px;
81 | border-right-width: 0;
82 | border-left-color: #fff;
83 | }
84 | .el-select-dropdown {
85 | position: absolute;
86 | z-index: 1001;
87 | border: 1px solid #e4e7ed;
88 | border-radius: 4px;
89 | background-color: #fff;
90 | -webkit-box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
91 | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
92 | -webkit-box-sizing: border-box;
93 | box-sizing: border-box;
94 | margin: 5px 0;
95 | }
96 | .el-select-dropdown.is-multiple .el-select-dropdown__item.selected {
97 | color: #000000;
98 | background-color: #fff;
99 | }
100 | .el-select-dropdown.is-multiple .el-select-dropdown__item.selected.hover {
101 | background-color: #f5f7fa;
102 | }
103 | .el-select-dropdown.is-multiple .el-select-dropdown__item.selected::after {
104 | position: absolute;
105 | right: 20px;
106 | font-family: element-icons;
107 | content: '\E611';
108 | font-size: 12px;
109 | font-weight: 700;
110 | -webkit-font-smoothing: antialiased;
111 | -moz-osx-font-smoothing: grayscale;
112 | }
113 | .el-select-dropdown .el-scrollbar.is-empty .el-select-dropdown__list {
114 | padding: 0;
115 | }
116 | .el-select-dropdown__empty {
117 | padding: 10px 0;
118 | margin: 0;
119 | text-align: center;
120 | color: #999;
121 | font-size: 14px;
122 | }
123 | .el-select-dropdown__wrap {
124 | max-height: 274px;
125 | }
126 | .el-select-dropdown__list {
127 | list-style: none;
128 | padding: 6px 0;
129 | margin: 0;
130 | -webkit-box-sizing: border-box;
131 | box-sizing: border-box;
132 | }
133 |
--------------------------------------------------------------------------------
/src/assets/styles/element/spinner.css:
--------------------------------------------------------------------------------
1 | .el-time-spinner {
2 | width: 100%;
3 | white-space: nowrap;
4 | }
5 | .el-spinner {
6 | display: inline-block;
7 | vertical-align: middle;
8 | }
9 | .el-spinner-inner {
10 | -webkit-animation: rotate 2s linear infinite;
11 | animation: rotate 2s linear infinite;
12 | width: 50px;
13 | height: 50px;
14 | }
15 | .el-spinner-inner .path {
16 | stroke: #ececec;
17 | stroke-linecap: round;
18 | -webkit-animation: dash 1.5s ease-in-out infinite;
19 | animation: dash 1.5s ease-in-out infinite;
20 | }
21 | @-webkit-keyframes rotate {
22 | 100% {
23 | -webkit-transform: rotate(360deg);
24 | transform: rotate(360deg);
25 | }
26 | }
27 | @keyframes rotate {
28 | 100% {
29 | -webkit-transform: rotate(360deg);
30 | transform: rotate(360deg);
31 | }
32 | }
33 | @-webkit-keyframes dash {
34 | 0% {
35 | stroke-dasharray: 1, 150;
36 | stroke-dashoffset: 0;
37 | }
38 | 50% {
39 | stroke-dasharray: 90, 150;
40 | stroke-dashoffset: -35;
41 | }
42 | 100% {
43 | stroke-dasharray: 90, 150;
44 | stroke-dashoffset: -124;
45 | }
46 | }
47 | @keyframes dash {
48 | 0% {
49 | stroke-dasharray: 1, 150;
50 | stroke-dashoffset: 0;
51 | }
52 | 50% {
53 | stroke-dasharray: 90, 150;
54 | stroke-dashoffset: -35;
55 | }
56 | 100% {
57 | stroke-dasharray: 90, 150;
58 | stroke-dashoffset: -124;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/assets/styles/element/step.css:
--------------------------------------------------------------------------------
1 | .el-step {
2 | position: relative;
3 | -ms-flex-negative: 1;
4 | flex-shrink: 1;
5 | }
6 | .el-step:last-of-type .el-step__line {
7 | display: none;
8 | }
9 | .el-step:last-of-type.is-flex {
10 | -ms-flex-preferred-size: auto !important;
11 | flex-basis: auto !important;
12 | -ms-flex-negative: 0;
13 | flex-shrink: 0;
14 | -webkit-box-flex: 0;
15 | -ms-flex-positive: 0;
16 | flex-grow: 0;
17 | }
18 | .el-step:last-of-type .el-step__description,
19 | .el-step:last-of-type .el-step__main {
20 | padding-right: 0;
21 | }
22 | .el-step__head {
23 | position: relative;
24 | width: 100%;
25 | }
26 | .el-step__head.is-process {
27 | color: #303133;
28 | border-color: #303133;
29 | }
30 | .el-step__head.is-wait {
31 | color: #c0c4cc;
32 | border-color: #c0c4cc;
33 | }
34 | .el-step__head.is-success {
35 | color: #67c23a;
36 | border-color: #67c23a;
37 | }
38 | .el-step__head.is-error {
39 | color: #f56c6c;
40 | border-color: #f56c6c;
41 | }
42 | .el-step__head.is-finish {
43 | color: #000000;
44 | border-color: #000000;
45 | }
46 | .el-step__icon {
47 | position: relative;
48 | z-index: 1;
49 | display: -webkit-inline-box;
50 | display: -ms-inline-flexbox;
51 | display: inline-flex;
52 | -webkit-box-pack: center;
53 | -ms-flex-pack: center;
54 | justify-content: center;
55 | -webkit-box-align: center;
56 | -ms-flex-align: center;
57 | align-items: center;
58 | width: 24px;
59 | height: 24px;
60 | font-size: 14px;
61 | -webkit-box-sizing: border-box;
62 | box-sizing: border-box;
63 | background: #fff;
64 | -webkit-transition: 0.15s ease-out;
65 | transition: 0.15s ease-out;
66 | }
67 | .el-step__icon.is-text {
68 | border-radius: 50%;
69 | border: 2px solid;
70 | border-color: inherit;
71 | }
72 | .el-step__icon.is-icon {
73 | width: 40px;
74 | }
75 | .el-step__icon-inner {
76 | display: inline-block;
77 | -webkit-user-select: none;
78 | -moz-user-select: none;
79 | -ms-user-select: none;
80 | user-select: none;
81 | text-align: center;
82 | font-weight: 700;
83 | line-height: 1;
84 | color: inherit;
85 | }
86 | .el-step__icon-inner[class*='el-icon']:not(.is-status) {
87 | font-size: 25px;
88 | font-weight: 400;
89 | }
90 | .el-step__icon-inner.is-status {
91 | -webkit-transform: translateY(1px);
92 | transform: translateY(1px);
93 | }
94 | .el-step__line {
95 | position: absolute;
96 | border-color: inherit;
97 | background-color: #c0c4cc;
98 | }
99 | .el-step__line-inner {
100 | display: block;
101 | border-width: 1px;
102 | border-style: solid;
103 | border-color: inherit;
104 | -webkit-transition: 0.15s ease-out;
105 | transition: 0.15s ease-out;
106 | -webkit-box-sizing: border-box;
107 | box-sizing: border-box;
108 | width: 0;
109 | height: 0;
110 | }
111 | .el-step__main {
112 | white-space: normal;
113 | text-align: left;
114 | }
115 | .el-step__title {
116 | font-size: 16px;
117 | line-height: 38px;
118 | }
119 | .el-step__title.is-process {
120 | font-weight: 700;
121 | color: #303133;
122 | }
123 | .el-step__title.is-wait {
124 | color: #c0c4cc;
125 | }
126 | .el-step__title.is-success {
127 | color: #67c23a;
128 | }
129 | .el-step__title.is-error {
130 | color: #f56c6c;
131 | }
132 | .el-step__title.is-finish {
133 | color: #000000;
134 | }
135 | .el-step__description {
136 | padding-right: 10%;
137 | margin-top: -5px;
138 | font-size: 12px;
139 | line-height: 20px;
140 | font-weight: 400;
141 | }
142 | .el-step__description.is-process {
143 | color: #303133;
144 | }
145 | .el-step__description.is-wait {
146 | color: #c0c4cc;
147 | }
148 | .el-step__description.is-success {
149 | color: #67c23a;
150 | }
151 | .el-step__description.is-error {
152 | color: #f56c6c;
153 | }
154 | .el-step__description.is-finish {
155 | color: #000000;
156 | }
157 | .el-step.is-horizontal {
158 | display: inline-block;
159 | }
160 | .el-step.is-horizontal .el-step__line {
161 | height: 2px;
162 | top: 11px;
163 | left: 0;
164 | right: 0;
165 | }
166 | .el-step.is-vertical {
167 | display: -webkit-box;
168 | display: -ms-flexbox;
169 | display: flex;
170 | }
171 | .el-step.is-vertical .el-step__head {
172 | -webkit-box-flex: 0;
173 | -ms-flex-positive: 0;
174 | flex-grow: 0;
175 | width: 24px;
176 | }
177 | .el-step.is-vertical .el-step__main {
178 | padding-left: 10px;
179 | -webkit-box-flex: 1;
180 | -ms-flex-positive: 1;
181 | flex-grow: 1;
182 | }
183 | .el-step.is-vertical .el-step__title {
184 | line-height: 24px;
185 | padding-bottom: 8px;
186 | }
187 | .el-step.is-vertical .el-step__line {
188 | width: 2px;
189 | top: 0;
190 | bottom: 0;
191 | left: 11px;
192 | }
193 | .el-step.is-vertical .el-step__icon.is-icon {
194 | width: 24px;
195 | }
196 | .el-step.is-center .el-step__head,
197 | .el-step.is-center .el-step__main {
198 | text-align: center;
199 | }
200 | .el-step.is-center .el-step__description {
201 | padding-left: 20%;
202 | padding-right: 20%;
203 | }
204 | .el-step.is-center .el-step__line {
205 | left: 50%;
206 | right: -50%;
207 | }
208 | .el-step.is-simple {
209 | display: -webkit-box;
210 | display: -ms-flexbox;
211 | display: flex;
212 | -webkit-box-align: center;
213 | -ms-flex-align: center;
214 | align-items: center;
215 | }
216 | .el-step.is-simple .el-step__head {
217 | width: auto;
218 | font-size: 0;
219 | padding-right: 10px;
220 | }
221 | .el-step.is-simple .el-step__icon {
222 | background: 0 0;
223 | width: 16px;
224 | height: 16px;
225 | font-size: 12px;
226 | }
227 | .el-step.is-simple .el-step__icon-inner[class*='el-icon']:not(.is-status) {
228 | font-size: 18px;
229 | }
230 | .el-step.is-simple .el-step__icon-inner.is-status {
231 | -webkit-transform: scale(0.8) translateY(1px);
232 | transform: scale(0.8) translateY(1px);
233 | }
234 | .el-step.is-simple .el-step__main {
235 | position: relative;
236 | display: -webkit-box;
237 | display: -ms-flexbox;
238 | display: flex;
239 | -webkit-box-align: stretch;
240 | -ms-flex-align: stretch;
241 | align-items: stretch;
242 | -webkit-box-flex: 1;
243 | -ms-flex-positive: 1;
244 | flex-grow: 1;
245 | }
246 | .el-step.is-simple .el-step__title {
247 | font-size: 16px;
248 | line-height: 20px;
249 | }
250 | .el-step.is-simple:not(:last-of-type) .el-step__title {
251 | max-width: 50%;
252 | word-break: break-all;
253 | }
254 | .el-step.is-simple .el-step__arrow {
255 | -webkit-box-flex: 1;
256 | -ms-flex-positive: 1;
257 | flex-grow: 1;
258 | display: -webkit-box;
259 | display: -ms-flexbox;
260 | display: flex;
261 | -webkit-box-align: center;
262 | -ms-flex-align: center;
263 | align-items: center;
264 | -webkit-box-pack: center;
265 | -ms-flex-pack: center;
266 | justify-content: center;
267 | }
268 | .el-step.is-simple .el-step__arrow::after,
269 | .el-step.is-simple .el-step__arrow::before {
270 | content: '';
271 | display: inline-block;
272 | position: absolute;
273 | height: 15px;
274 | width: 1px;
275 | background: #c0c4cc;
276 | }
277 | .el-step.is-simple .el-step__arrow::before {
278 | -webkit-transform: rotate(-45deg) translateY(-4px);
279 | transform: rotate(-45deg) translateY(-4px);
280 | -webkit-transform-origin: 0 0;
281 | transform-origin: 0 0;
282 | }
283 | .el-step.is-simple .el-step__arrow::after {
284 | -webkit-transform: rotate(45deg) translateY(4px);
285 | transform: rotate(45deg) translateY(4px);
286 | -webkit-transform-origin: 100% 100%;
287 | transform-origin: 100% 100%;
288 | }
289 | .el-step.is-simple:last-of-type .el-step__arrow {
290 | display: none;
291 | }
292 |
--------------------------------------------------------------------------------
/src/assets/styles/element/steps.css:
--------------------------------------------------------------------------------
1 | .el-steps {
2 | display: -webkit-box;
3 | display: -ms-flexbox;
4 | display: flex;
5 | }
6 | .el-steps--simple {
7 | padding: 13px 8%;
8 | border-radius: 4px;
9 | background: #f5f7fa;
10 | }
11 | .el-steps--horizontal {
12 | white-space: nowrap;
13 | }
14 | .el-steps--vertical {
15 | height: 100%;
16 | -webkit-box-orient: vertical;
17 | -webkit-box-direction: normal;
18 | -ms-flex-flow: column;
19 | flex-flow: column;
20 | }
21 |
--------------------------------------------------------------------------------
/src/assets/styles/element/submenu.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/src/assets/styles/element/submenu.css
--------------------------------------------------------------------------------
/src/assets/styles/element/switch.css:
--------------------------------------------------------------------------------
1 | .el-switch {
2 | display: -webkit-inline-box;
3 | display: -ms-inline-flexbox;
4 | display: inline-flex;
5 | -webkit-box-align: center;
6 | -ms-flex-align: center;
7 | align-items: center;
8 | position: relative;
9 | font-size: 14px;
10 | line-height: 20px;
11 | height: 20px;
12 | vertical-align: middle;
13 | }
14 | .el-switch.is-disabled .el-switch__core,
15 | .el-switch.is-disabled .el-switch__label {
16 | cursor: not-allowed;
17 | }
18 | .el-switch__core,
19 | .el-switch__label {
20 | display: inline-block;
21 | cursor: pointer;
22 | vertical-align: middle;
23 | }
24 | .el-switch__label {
25 | -webkit-transition: 0.2s;
26 | transition: 0.2s;
27 | height: 20px;
28 | font-size: 14px;
29 | font-weight: 500;
30 | color: #303133;
31 | }
32 | .el-switch__label.is-active {
33 | color: #000000;
34 | }
35 | .el-switch__label--left {
36 | margin-right: 10px;
37 | }
38 | .el-switch__label--right {
39 | margin-left: 10px;
40 | }
41 | .el-switch__label * {
42 | line-height: 1;
43 | font-size: 14px;
44 | display: inline-block;
45 | }
46 | .el-switch__input {
47 | position: absolute;
48 | width: 0;
49 | height: 0;
50 | opacity: 0;
51 | margin: 0;
52 | }
53 | .el-switch__input:focus ~ .el-switch__core {
54 | outline: #000000 solid 1px;
55 | }
56 | .el-switch__core {
57 | margin: 0;
58 | position: relative;
59 | width: 40px;
60 | height: 20px;
61 | border: 1px solid #dcdfe6;
62 | outline: 0;
63 | border-radius: 10px;
64 | -webkit-box-sizing: border-box;
65 | box-sizing: border-box;
66 | background: #dcdfe6;
67 | -webkit-transition: border-color 0.3s, background-color 0.3s;
68 | transition: border-color 0.3s, background-color 0.3s;
69 | }
70 | .el-switch__core:after {
71 | content: '';
72 | position: absolute;
73 | top: 1px;
74 | left: 1px;
75 | border-radius: 100%;
76 | -webkit-transition: all 0.3s;
77 | transition: all 0.3s;
78 | width: 16px;
79 | height: 16px;
80 | background-color: #fff;
81 | }
82 | .el-switch.is-checked .el-switch__core {
83 | border-color: #000000;
84 | background-color: #000000;
85 | }
86 | .el-switch.is-checked .el-switch__core::after {
87 | left: 100%;
88 | margin-left: -17px;
89 | }
90 | .el-switch.is-disabled {
91 | opacity: 0.6;
92 | }
93 | .el-switch--wide .el-switch__label.el-switch__label--left span {
94 | left: 10px;
95 | }
96 | .el-switch--wide .el-switch__label.el-switch__label--right span {
97 | right: 10px;
98 | }
99 | .el-switch .label-fade-enter,
100 | .el-switch .label-fade-leave-active {
101 | opacity: 0;
102 | }
103 |
--------------------------------------------------------------------------------
/src/assets/styles/element/tab-pane.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nicejade/markdown-online-editor/58c38df82615de4b816bddbb53031df8c1347e02/src/assets/styles/element/tab-pane.css
--------------------------------------------------------------------------------
/src/assets/styles/element/tag.css:
--------------------------------------------------------------------------------
1 | .el-tag {
2 | background-color: rgba(64, 158, 255, 0.1);
3 | display: inline-block;
4 | padding: 0 10px;
5 | height: 32px;
6 | line-height: 30px;
7 | font-size: 12px;
8 | color: #000000;
9 | border-radius: 4px;
10 | -webkit-box-sizing: border-box;
11 | box-sizing: border-box;
12 | border: 1px solid rgba(64, 158, 255, 0.2);
13 | white-space: nowrap;
14 | }
15 | .el-tag .el-icon-close {
16 | border-radius: 50%;
17 | text-align: center;
18 | position: relative;
19 | cursor: pointer;
20 | font-size: 12px;
21 | height: 16px;
22 | width: 16px;
23 | line-height: 16px;
24 | vertical-align: middle;
25 | top: -1px;
26 | right: -5px;
27 | color: #000000;
28 | }
29 | .el-tag .el-icon-close::before {
30 | display: block;
31 | }
32 | .el-tag .el-icon-close:hover {
33 | background-color: #000000;
34 | color: #fff;
35 | }
36 | .el-tag--info,
37 | .el-tag--info .el-tag__close {
38 | color: #909399;
39 | }
40 | .el-tag--info {
41 | background-color: rgba(144, 147, 153, 0.1);
42 | border-color: rgba(144, 147, 153, 0.2);
43 | }
44 | .el-tag--info.is-hit {
45 | border-color: #909399;
46 | }
47 | .el-tag--info .el-tag__close:hover {
48 | background-color: #909399;
49 | color: #fff;
50 | }
51 | .el-tag--success {
52 | background-color: rgba(103, 194, 58, 0.1);
53 | border-color: rgba(103, 194, 58, 0.2);
54 | color: #67c23a;
55 | }
56 | .el-tag--success.is-hit {
57 | border-color: #67c23a;
58 | }
59 | .el-tag--success .el-tag__close {
60 | color: #67c23a;
61 | }
62 | .el-tag--success .el-tag__close:hover {
63 | background-color: #67c23a;
64 | color: #fff;
65 | }
66 | .el-tag--warning {
67 | background-color: rgba(230, 162, 60, 0.1);
68 | border-color: rgba(230, 162, 60, 0.2);
69 | color: #e6a23c;
70 | }
71 | .el-tag--warning.is-hit {
72 | border-color: #e6a23c;
73 | }
74 | .el-tag--warning .el-tag__close {
75 | color: #e6a23c;
76 | }
77 | .el-tag--warning .el-tag__close:hover {
78 | background-color: #e6a23c;
79 | color: #fff;
80 | }
81 | .el-tag--danger {
82 | background-color: rgba(245, 108, 108, 0.1);
83 | border-color: rgba(245, 108, 108, 0.2);
84 | color: #f56c6c;
85 | }
86 | .el-tag--danger.is-hit {
87 | border-color: #f56c6c;
88 | }
89 | .el-tag--danger .el-tag__close {
90 | color: #f56c6c;
91 | }
92 | .el-tag--danger .el-tag__close:hover {
93 | background-color: #f56c6c;
94 | color: #fff;
95 | }
96 | .el-tag--medium {
97 | height: 28px;
98 | line-height: 26px;
99 | }
100 | .el-tag--medium .el-icon-close {
101 | -webkit-transform: scale(0.8);
102 | transform: scale(0.8);
103 | }
104 | .el-tag--small {
105 | height: 24px;
106 | padding: 0 8px;
107 | line-height: 22px;
108 | }
109 | .el-tag--small .el-icon-close {
110 | -webkit-transform: scale(0.8);
111 | transform: scale(0.8);
112 | }
113 | .el-tag--mini {
114 | height: 20px;
115 | padding: 0 5px;
116 | line-height: 19px;
117 | }
118 | .el-tag--mini .el-icon-close {
119 | margin-left: -3px;
120 | -webkit-transform: scale(0.7);
121 | transform: scale(0.7);
122 | }
123 |
--------------------------------------------------------------------------------
/src/assets/styles/element/tooltip.css:
--------------------------------------------------------------------------------
1 | .el-tooltip:focus:hover,
2 | .el-tooltip:focus:not(.focusing) {
3 | outline-width: 0;
4 | }
5 | .el-tooltip__popper {
6 | position: absolute;
7 | border-radius: 4px;
8 | padding: 10px;
9 | z-index: 2000;
10 | font-size: 12px;
11 | line-height: 1.2;
12 | min-width: 10px;
13 | }
14 | .el-tooltip__popper .popper__arrow,
15 | .el-tooltip__popper .popper__arrow::after {
16 | position: absolute;
17 | display: block;
18 | width: 0;
19 | height: 0;
20 | border-color: transparent;
21 | border-style: solid;
22 | }
23 | .el-tooltip__popper .popper__arrow {
24 | border-width: 6px;
25 | }
26 | .el-tooltip__popper .popper__arrow::after {
27 | content: ' ';
28 | border-width: 5px;
29 | }
30 | .el-tooltip__popper[x-placement^='top'] {
31 | margin-bottom: 12px;
32 | }
33 | .el-tooltip__popper[x-placement^='top'] .popper__arrow {
34 | bottom: -6px;
35 | border-top-color: #303133;
36 | border-bottom-width: 0;
37 | }
38 | .el-tooltip__popper[x-placement^='top'] .popper__arrow::after {
39 | bottom: 1px;
40 | margin-left: -5px;
41 | border-top-color: #303133;
42 | border-bottom-width: 0;
43 | }
44 | .el-tooltip__popper[x-placement^='bottom'] {
45 | margin-top: 12px;
46 | }
47 | .el-tooltip__popper[x-placement^='bottom'] .popper__arrow {
48 | top: -6px;
49 | border-top-width: 0;
50 | border-bottom-color: #303133;
51 | }
52 | .el-tooltip__popper[x-placement^='bottom'] .popper__arrow::after {
53 | top: 1px;
54 | margin-left: -5px;
55 | border-top-width: 0;
56 | border-bottom-color: #303133;
57 | }
58 | .el-tooltip__popper[x-placement^='right'] {
59 | margin-left: 12px;
60 | }
61 | .el-tooltip__popper[x-placement^='right'] .popper__arrow {
62 | left: -6px;
63 | border-right-color: #303133;
64 | border-left-width: 0;
65 | }
66 | .el-tooltip__popper[x-placement^='right'] .popper__arrow::after {
67 | bottom: -5px;
68 | left: 1px;
69 | border-right-color: #303133;
70 | border-left-width: 0;
71 | }
72 | .el-tooltip__popper[x-placement^='left'] {
73 | margin-right: 12px;
74 | }
75 | .el-tooltip__popper[x-placement^='left'] .popper__arrow {
76 | right: -6px;
77 | border-right-width: 0;
78 | border-left-color: #303133;
79 | }
80 | .el-tooltip__popper[x-placement^='left'] .popper__arrow::after {
81 | right: 1px;
82 | bottom: -5px;
83 | margin-left: -5px;
84 | border-right-width: 0;
85 | border-left-color: #303133;
86 | }
87 | .el-tooltip__popper.is-dark {
88 | background: #303133;
89 | color: #fff;
90 | }
91 | .el-tooltip__popper.is-light {
92 | background: #fff;
93 | border: 1px solid #303133;
94 | }
95 | .el-tooltip__popper.is-light[x-placement^='top'] .popper__arrow {
96 | border-top-color: #303133;
97 | }
98 | .el-tooltip__popper.is-light[x-placement^='top'] .popper__arrow::after {
99 | border-top-color: #fff;
100 | }
101 | .el-tooltip__popper.is-light[x-placement^='bottom'] .popper__arrow {
102 | border-bottom-color: #303133;
103 | }
104 | .el-tooltip__popper.is-light[x-placement^='bottom'] .popper__arrow::after {
105 | border-bottom-color: #fff;
106 | }
107 | .el-tooltip__popper.is-light[x-placement^='left'] .popper__arrow {
108 | border-left-color: #303133;
109 | }
110 | .el-tooltip__popper.is-light[x-placement^='left'] .popper__arrow::after {
111 | border-left-color: #fff;
112 | }
113 | .el-tooltip__popper.is-light[x-placement^='right'] .popper__arrow {
114 | border-right-color: #303133;
115 | }
116 | .el-tooltip__popper.is-light[x-placement^='right'] .popper__arrow::after {
117 | border-right-color: #fff;
118 | }
119 |
--------------------------------------------------------------------------------
/src/assets/styles/element/tree.css:
--------------------------------------------------------------------------------
1 | .el-tree {
2 | position: relative;
3 | cursor: default;
4 | background: #fff;
5 | color: #606266;
6 | }
7 | .el-tree__empty-block {
8 | position: relative;
9 | min-height: 60px;
10 | text-align: center;
11 | width: 100%;
12 | height: 100%;
13 | }
14 | .el-tree__empty-text {
15 | position: absolute;
16 | left: 50%;
17 | top: 50%;
18 | -webkit-transform: translate(-50%, -50%);
19 | transform: translate(-50%, -50%);
20 | color: #6f7180;
21 | }
22 | .el-tree__drop-indicator {
23 | position: absolute;
24 | left: 0;
25 | right: 0;
26 | height: 1px;
27 | background-color: #000000;
28 | }
29 | .el-tree-node {
30 | white-space: nowrap;
31 | outline: 0;
32 | }
33 | .el-tree-node:focus > .el-tree-node__content {
34 | background-color: #f5f7fa;
35 | }
36 | .el-tree-node.is-drop-inner > .el-tree-node__content .el-tree-node__label {
37 | background-color: #000000;
38 | color: #fff;
39 | }
40 | .el-tree-node__content {
41 | display: -webkit-box;
42 | display: -ms-flexbox;
43 | display: flex;
44 | -webkit-box-align: center;
45 | -ms-flex-align: center;
46 | align-items: center;
47 | height: 26px;
48 | cursor: pointer;
49 | }
50 | .el-tree-node__content > .el-tree-node__expand-icon {
51 | padding: 6px;
52 | }
53 | .el-tree-node__content > .el-checkbox {
54 | margin-right: 8px;
55 | }
56 | .el-tree-node__content:hover {
57 | background-color: #f5f7fa;
58 | }
59 | .el-tree.is-dragging .el-tree-node__content {
60 | cursor: move;
61 | }
62 | .el-tree.is-dragging .el-tree-node__content * {
63 | pointer-events: none;
64 | }
65 | .el-tree.is-dragging.is-drop-not-allow .el-tree-node__content {
66 | cursor: not-allowed;
67 | }
68 | .el-tree-node__expand-icon {
69 | cursor: pointer;
70 | color: #c0c4cc;
71 | font-size: 12px;
72 | -webkit-transform: rotate(0);
73 | transform: rotate(0);
74 | -webkit-transition: -webkit-transform 0.3s ease-in-out;
75 | transition: -webkit-transform 0.3s ease-in-out;
76 | transition: transform 0.3s ease-in-out;
77 | transition: transform 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out;
78 | }
79 | .el-tree-node__expand-icon.expanded {
80 | -webkit-transform: rotate(90deg);
81 | transform: rotate(90deg);
82 | }
83 | .el-tree-node__expand-icon.is-leaf {
84 | color: transparent;
85 | cursor: default;
86 | }
87 | .el-tree-node__label {
88 | font-size: 14px;
89 | }
90 | .el-tree-node__loading-icon {
91 | margin-right: 8px;
92 | font-size: 14px;
93 | color: #c0c4cc;
94 | }
95 | .el-tree-node > .el-tree-node__children {
96 | overflow: hidden;
97 | background-color: transparent;
98 | }
99 | .el-tree-node.is-expanded > .el-tree-node__children {
100 | display: block;
101 | }
102 | .el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {
103 | background-color: #f0f7ff;
104 | }
105 |
--------------------------------------------------------------------------------
/src/assets/styles/mixins.less:
--------------------------------------------------------------------------------
1 | /* Clearfix
2 | For modern browsers
3 | 1. The space content is one way to avoid an Opera bug when the
4 | contenteditable attribute is included anywhere else in the document.
5 | Otherwise it causes space to appear at the top and bottom of elements
6 | that are clearfixed.
7 | 2. The use of `table` rather than `block` is only necessary if using
8 | `:before` to contain the top-margins of child elements.
9 | Source: http://nicolasgallagher.com/micro-clearfix-hack */
10 | .clearfix() {
11 | &:before,
12 | &:after {
13 | content: ' ';
14 | display: table;
15 | }
16 | &:after {
17 | clear: both;
18 | }
19 | }
20 |
21 | // (Responsive image)Keep images from scaling beyond the width of their parents.
22 | .img-responsive(@display: block) {
23 | display: @display;
24 | max-width: 100%;
25 | height: auto;
26 | }
27 |
28 | // Resize anything
29 | .resizable(@direction) {
30 | resize: @direction;
31 | overflow: auto;
32 | }
33 |
34 | // Text overflow
35 | // Requires inline-block or block for proper styling
36 | .text-overflow() {
37 | overflow: hidden;
38 | text-overflow: ellipsis;
39 | white-space: nowrap;
40 | }
41 |
42 | // Center-align a block level element
43 | .center-block() {
44 | display: block;
45 | margin-left: auto;
46 | margin-right: auto;
47 | }
48 |
49 | .absolute-center() {
50 | position: absolute;
51 | top: 50%;
52 | left: 50%;
53 | transform: translate(-50%, -50%);
54 | }
55 |
56 | .fixed-center() {
57 | position: fixed;
58 | top: 50%;
59 | left: 50%;
60 | transform: translate(-50%, -50%);
61 | }
62 |
63 | .flex-box-center(@direction: row, @justify: center, @align-items: center) {
64 | flex-direction: @direction;
65 | display: -webkit-box;
66 | display: -moz-box;
67 | display: -webkit-flex;
68 | display: -ms-flex;
69 | display: flex;
70 | -webkit-box-align: center;
71 | -moz-box-align: center;
72 | -ms-box-align: center;
73 | -webkit-align-items: @align-items;
74 | -ms-align-items: @align-items;
75 | align-items: @align-items;
76 | -webkit-box-pack: center;
77 | -webkit-justify-content: center;
78 | justify-content: @justify;
79 | }
80 |
--------------------------------------------------------------------------------
/src/assets/styles/style.less:
--------------------------------------------------------------------------------
1 | @import 'variables.less';
2 | @import 'element.less';
3 | @import 'mixins.less';
4 | @import 'common.less';
5 |
--------------------------------------------------------------------------------
/src/assets/styles/variables.less:
--------------------------------------------------------------------------------
1 | @size-factor: 0.5rem;
2 |
3 | @brand: #03a9f4;
4 |
5 | @bg-grey: #fafcff;
6 | @input-grey: #f2f4f7;
7 | @text-grey: #6a8bad;
8 | @icon-grey: #707780;
9 |
10 | @border-grey: #d7dce5;
11 | @border-black: #7a8ba9;
12 |
13 | @deep-black: #1a2a3a;
14 | @black: #2a3a4a;
15 | @liht-black: #3a4a5a;
16 |
17 | @white: #ffffff;
18 | @red: #fa0101;
19 | @grey: #e8ebf1;
20 | @orange: #6b5900;
21 | @yellow: #ffe564;
22 |
23 | @font-large: 2.1rem;
24 | @font-medium: 1.3rem;
25 | @font-small: 1rem;
26 |
27 | @header-height: 60px;
28 | @max-body-width: 1440px;
29 |
30 | @el-message-zindex: 10000;
31 | @hint-css-zindex: 9999;
32 |
--------------------------------------------------------------------------------
/src/components/Advertisement.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
15 |
57 |
58 |
85 |
--------------------------------------------------------------------------------
/src/components/Icon.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
35 |
36 |
43 |
--------------------------------------------------------------------------------
/src/components/PreviewVditor.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
61 |
62 |
131 |
--------------------------------------------------------------------------------
/src/components/icons/Arrow.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
38 |
39 |
64 |
--------------------------------------------------------------------------------
/src/config/aboutArya.js:
--------------------------------------------------------------------------------
1 | /** @format */
2 |
3 | export default `# [Arya](https://markdown.lovejade.cn/?utm_source=markdown.lovejade.cn&pid=about-arya) - 在线 Markdown 编辑器
4 |
5 | [Arya](https://markdown.lovejade.cn/?utm_source=markdown.lovejade.cn&pid=about-arya),是一款基于 [Vue2](https://site.lovejade.cn/post/5b1a221c0526c920d6dfaada)、[Vditor](https://github.com/Vanessa219/vditor),为未来而构建的在线 [Markdown](https://github.com/nicejade/nice-front-end-tutorial/blob/master/tutorial/markdown-tutorial.md) 编辑器;轻量且强大:内置粘贴 HTML 自动转换为 Markdown,支持流程图、甘特图、时序图、任务列表,可导出携带样式的图片、PDF、微信公众号特制的 HTML 等等。
6 |
7 | >**微注**:[Arya](https://markdown.lovejade.cn/?utm_source=markdown.lovejade.cn&pid=about-arya) 另一大优点在于:编辑内容只会在您本地进行保存,不会上传您的数据至服务器,**绝不窥测用户个人隐私,可放心使用**;Github 源码:[markdown-online-editor](https://github.com/nicejade/markdown-online-editor),部分功能仍在开发🚧,敬请期待。
8 |
9 | **背景初衷**:早期就有关注到由"黑客派"所出品的 [Vditor](https://github.com/Vanessa219/vditor):一款为未来而构建的下一代 [Markdown](https://github.com/nicejade/nice-front-end-tutorial/blob/master/tutorial/markdown-tutorial.md) 编辑器。然,现而今市面上所存在的 \`Markdown\` 编辑器,或多或少都存在一些问题(或功能不全,或高级功能收费...),因此基于自身所需,加之 [Vditor](https://github.com/Vanessa219/vditor) 的强大,就诞生了做一款[在线 Markdown 编辑器](https://markdown.lovejade.cn/?utm_source=github.com) 的念头;取其名曰 [\`Arya\`(二丫)](https://quickapp.lovejade.cn/talking-game-of-thrones/?utm_source=markdown.lovejade.cn)。
10 |
11 |
31 |
32 | ------
33 |
34 | ## 什么是 Markdown
35 |
36 | \`Markdown\` 是一种方便记忆、书写的纯文本标记语言,用户可以使用这些标记符号,以最小的输入代价,生成极富表现力的文档:譬如您正在阅读的这份文档。它使用简单的符号标记不同的标题,分割不同的段落,**粗体**、*斜体* 或者[超文本链接](https://vue-cli3.lovejade.cn/explore/),更棒的是,它还可以:
37 |
38 | ### 1. 制作待办事宜 \`Todo\` 列表
39 |
40 | - [x] 🎉 通常 \`Markdown\` 解析器自带的基本功能;
41 | - [x] 🍀 支持**流程图**、**甘特图**、**时序图**、**任务列表**;
42 | - [x] 🏁 支持粘贴 HTML 自动转换为 Markdown;
43 | - [x] 💃🏻 支持插入原生 Emoji、设置常用表情列表;
44 | - [x] 🚑 支持编辑内容保存**本地存储**,防止意外丢失;
45 | - [x] 📝 支持**实时预览**,主窗口大小拖拽,字符计数;
46 | - [x] 🛠 支持常用快捷键(**Tab**),及代码块添加复制
47 | - [x] ✨ 支持**导出**携带样式的 PDF、PNG、JPEG 等;
48 | - [x] ✨ 升级 Vditor,新增对 \`echarts\` 图表的支持;
49 | - [x] ✨ 注入 [RevealJs](https://revealjs.com/#/),增设对 \`PPT\` 预览支持;
50 | - [x] 👏 支持检查并格式化 Markdown 语法,使其专业;
51 | - [x] 🦑 支持五线谱、及[部分站点、视频、音频解析](https://github.com/b3log/vditor/issues/117?utm_source=hacpai.com#issuecomment-526986052);
52 | - [x] 🌟 增加对**所见即所得**编辑模式的支持(\`⌘-⇧-M\`);
53 |
54 | ### 2. 书写一个质能守恒公式[^LaTeX]
55 |
56 | $$
57 | E=mc^2
58 | $$
59 |
60 | ### 3. 高亮一段代码[^code]
61 |
62 | \`\`\`js
63 | // 给页面里所有的 DOM 元素添加一个 1px 的描边(outline);
64 | [].forEach.call($$("*"),function(a){
65 | a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).toString(16);
66 | })
67 | \`\`\`
68 |
69 | ### 4. 高效绘制[流程图](https://github.com/knsv/mermaid#flowchart)
70 |
71 | \`\`\`mermaid
72 | graph TD
73 | A[用户请求] --> B[语义解析]
74 | B --> C[RAG检索]
75 |
76 | C -->|✅ 知识库匹配| D[上下文增强]
77 | C -->|❌ 无匹配| E[任务分解]
78 |
79 | D --> E
80 |
81 | E --> F{工具选择}
82 |
83 | F -->|🛠️ 核心工具| G{基础操作}
84 | F -->|🔌 MCP扩展服务| H{MCP操作}
85 |
86 | G -->|✏️ 文件操作| I[读写/替换]
87 | G -->|🖥️ 系统命令执行| J[执行命令]
88 | G -->|🔍 代码分析| K[代码分析]
89 |
90 | H -->|⚙️ 使用MCP工具| L[使用MCP工具]
91 | H -->|📦 访问MCP资源| M[访问MCP资源]
92 |
93 | I --> N[结果验证]
94 | J --> N
95 | K --> N
96 | L --> N
97 | M --> N
98 |
99 | N --> O{完成判断}
100 |
101 | O -->|✅| P[提交最终结果]
102 | O -->|❌| E
103 | \`\`\`
104 |
105 | ### 5. 高效绘制[序列图](https://github.com/knsv/mermaid#sequence-diagram)
106 |
107 | \`\`\`
108 | sequenceDiagram
109 | participant Alice
110 | participant Bob
111 | Alice->John: Hello John, how are you?
112 | loop Healthcheck
113 | John->John: Fight against hypochondria
114 | end
115 | Note right of John: Rational thoughts
prevail...
116 | John-->Alice: Great!
117 | John->Bob: How about you?
118 | Bob-->John: Jolly good!
119 | \`\`\`
120 |
121 | \`\`\`mermaid
122 | sequenceDiagram
123 | participant Alice
124 | participant Bob
125 | Alice->John: Hello John, how are you?
126 | loop Healthcheck
127 | John->John: Fight against hypochondria
128 | end
129 | Note right of John: Rational thoughts
prevail...
130 | John-->Alice: Great!
131 | John->Bob: How about you?
132 | Bob-->John: Jolly good!
133 | \`\`\`
134 |
135 | ### 6. 高效绘制[甘特图](https://github.com/knsv/mermaid#gantt-diagram)
136 |
137 | >**甘特图**内在思想简单。基本是一条线条图,横轴表示时间,纵轴表示活动(项目),线条表示在整个期间上计划和实际的活动完成情况。它直观地表明任务计划在什么时候进行,及实际进展与计划要求的对比。
138 |
139 | \`\`\`
140 | gantt
141 | title 项目开发流程
142 | section 项目确定
143 | 需求分析 :a1, 2019-06-22, 3d
144 | 可行性报告 :after a1, 5d
145 | 概念验证 : 5d
146 | section 项目实施
147 | 概要设计 :2019-07-05 , 5d
148 | 详细设计 :2019-07-08, 10d
149 | 编码 :2019-07-15, 10d
150 | 测试 :2019-07-22, 5d
151 | section 发布验收
152 | 发布: 2d
153 | 验收: 3d
154 | \`\`\`
155 |
156 | \`\`\`mermaid
157 | gantt
158 | title 项目开发流程
159 | section 项目确定
160 | 需求分析 :a1, 2019-06-22, 3d
161 | 可行性报告 :after a1, 5d
162 | 概念验证 : 5d
163 | section 项目实施
164 | 概要设计 :2019-07-05 , 5d
165 | 详细设计 :2019-07-08, 10d
166 | 编码 :2019-07-15, 10d
167 | 测试 :2019-07-22, 5d
168 | section 发布验收
169 | 发布: 2d
170 | 验收: 3d
171 | \`\`\`
172 |
173 | ### 7. 绘制表格
174 |
175 | | 作品名称 | 在线地址 | 上线日期 |
176 | | :-------- | :----- | :----: |
177 | | 逍遥自在轩 | [https://niceshare.site](https://niceshare.site/?ref=markdown.lovejade.cn) |2024-04-26|
178 | | 玉桃文飨轩 | [https://share.lovejade.cn](https://share.lovejade.cn/?ref=markdown.lovejade.cn) |2022-08-26|
179 | | 缘知随心庭 | [https://fine.niceshare.site](https://fine.niceshare.site/?ref=markdown.lovejade.cn) |2022-02-26|
180 | | 静轩之别苑 | [http://quickapp.lovejade.cn](http://quickapp.lovejade.cn/?ref=markdown.lovejade.cn) |2019-01-12|
181 | | 晚晴幽草轩 | [https://www.jeffjade.com](https://www.jeffjade.com/?ref=markdown.lovejade.cn) |2014-09-20|
182 |
183 | ### 8. 支持部分站点、视频、音频解析
184 |
185 | [飞雪连天射白鹿,笑书神侠倚碧鸳](https://img.hacpai.com/file/2018/11/-97d5cec5.mp4)
186 |
187 | ### 9. 更详细语法说明
188 |
189 | 想要查看更详细的语法说明,可以参考这份 [Markdown 资源列表](https://github.com/nicejade/nice-front-end-tutorial/blob/master/tutorial/markdown-tutorial.md),涵盖入门至进阶教程,以及资源、平台等信息,能让您对她有更深的认知。
190 |
191 | 总而言之,不同于其它*所见即所得*的编辑器:你只需使用键盘专注于书写文本内容,就可以生成印刷级的排版格式,省却在键盘和工具栏之间来回切换,调整内容和格式的麻烦。**Markdown 在流畅的书写和印刷级的阅读体验之间找到了平衡。** 目前它已经成为世界上最大的技术分享网站 \`GitHub\` 和 技术问答网站 \`StackOverFlow\` 的御用书写格式,而且越发流行,正在在向各行业渗透。
192 |
193 | ---
194 |
195 | ## 相关链接
196 |
197 | - [清风明月轩](https://www.thebettersites.com/?ref=github.com)
198 | - [逍遥自在轩](https://www.niceshare.site/?ref=github.com)
199 | - [晚晴幽草轩](https://www.jeffjade.com/nicelinks?ref=github.com)
200 | - [缘知随心庭](https://fine.niceshare.site/?ref=github.com)
201 | - [静轩之别苑](https://quickapp.lovejade.cn/?ref=github.com)
202 | - [悠然宜想亭](https://forum.lovejade.cn/?ref=github.com)
203 | - [天意人间舫](https://blog.lovejade.cn/?utm_source=github.com)
204 | - [SegmentFault](https://segmentfault.com/u/jeffjade)
205 | - [X(Twitter)](https://x.com/MarshalXuan)
206 | `
207 |
--------------------------------------------------------------------------------
/src/config/constant.js:
--------------------------------------------------------------------------------
1 | /** @format */
2 |
3 | export const appTitle = 'Arya - 在线 Markdown 编辑器'
4 |
5 | export const exportTextMap = {
6 | '/export/png': '导出 PNG',
7 | '/export/pdf': '导出 PDF',
8 | '/export/ppt': 'PPT 预览',
9 | }
10 |
--------------------------------------------------------------------------------
/src/config/default.js:
--------------------------------------------------------------------------------
1 | /** @format */
2 |
3 | const echartsConf = {
4 | backgroundColor: '#212121',
5 | title: {
6 | text: '「晚晴幽草轩」访问来源',
7 | subtext: '2019 年 6 月份',
8 | x: 'center',
9 | textStyle: {
10 | color: '#f2f2f2',
11 | },
12 | },
13 | tooltip: {
14 | trigger: 'item',
15 | formatter: '{a}
{b} : {c} ({d}%)',
16 | },
17 | legend: {
18 | orient: 'vertical',
19 | left: 'left',
20 | data: ['搜索引擎', '直接访问', '推荐', '其他', '社交平台'],
21 | textStyle: {
22 | color: '#f2f2f2',
23 | },
24 | },
25 | series: [
26 | {
27 | name: '访问来源',
28 | type: 'pie',
29 | radius: '55%',
30 | center: ['50%', '60%'],
31 | data: [
32 | { value: 10440, name: '搜索引擎', itemStyle: { color: '#ef4136' } },
33 | { value: 4770, name: '直接访问' },
34 | { value: 2430, name: '推荐' },
35 | { value: 342, name: '其他' },
36 | { value: 18, name: '社交平台' },
37 | ],
38 | itemStyle: {
39 | emphasis: {
40 | shadowBlur: 10,
41 | shadowOffsetX: 0,
42 | shadowColor: 'rgba(0, 0, 0, 0.5)',
43 | },
44 | },
45 | },
46 | ],
47 | }
48 |
49 | const echartsDemoJsonStr = JSON.stringify(echartsConf, null, 2)
50 |
51 | export default `# 欢迎使用 \`Arya\` 在线 Markdown 编辑器
52 |
53 | [Arya](https://markdown.lovejade.cn/?ref=markdown.lovejade.cn),是一款基于 \`Vue\`、\`Vditor\`,为未来而构建的在线 Markdown 编辑器;轻量且强大:内置粘贴 HTML 自动转换为 Markdown,支持流程图、甘特图、时序图、任务列表,可导出携带样式的图片、PDF、微信公众号特制的 HTML 等等。
54 |
55 | ---
56 |
57 | ## 如何使用
58 |
59 | **微注**:清空目前这份默认文档,即处于可使用态。[Arya](https://markdown.lovejade.cn/?ref=markdown.lovejade.cn) 另一大优点在于:编辑内容只会在您本地进行保存,不会上传您的数据至服务器,**绝不窥测用户个人隐私,可放心使用**;Github 源码:[markdown-online-editor](https://github.com/nicejade/markdown-online-editor),部分功能仍在开发🚧,敬请期待。
60 |
61 | 默认为[所见即所得](https://hacpai.com/article/1577370404903?ref=github.com)模式,可通过 \`⌘-⇧-M\`(\`Ctrl-⇧-M\`)进行切换;或通过以下方式:
62 | - 所见即所得:\`⌘-⌥-7\`(\`Ctrl-alt-7\`);
63 | - 即时渲染:\`⌘-⌥-8\`(\`Ctrl-alt-8\`);
64 | - 分屏渲染:\`⌘-⌥-9\`(\`Ctrl-alt-9\`);
65 |
66 | ### PPT 预览
67 |
68 | 如果您用作 \`PPT\` 预览(入口在\`设置\`中),需要注意,这里暂还不能支持各种图表的渲染;您可以使用 \`---\` 来定义水平方向上幻灯片,用 \`--\` 来定义垂直幻灯片;更多设定可以参见 [RevealJs 文档](https://github.com/hakimel/reveal.js#table-of-contents)。
69 |
70 |
71 | ---
72 |
73 | ## 什么是 Markdown
74 |
75 | \`Markdown\` 是一种方便记忆、书写的纯文本标记语言,用户可以使用这些标记符号,以最小的输入代价,生成极富表现力的文档:譬如您正在阅读的这份文档。它使用简单的符号标记不同的标题,分割不同的段落,**粗体**、*斜体* 或者[超文本链接](https://vue-cli3.lovejade.cn/explore/),更棒的是,它还可以:
76 |
77 | ---
78 |
79 | ### 1. 制作待办事宜 \`Todo\` 列表
80 |
81 | - [x] 🎉 通常 \`Markdown\` 解析器自带的基本功能;
82 | - [x] 🍀 支持**流程图**、**甘特图**、**时序图**、**任务列表**;
83 | - [x] 🏁 支持粘贴 HTML 自动转换为 Markdown;
84 | - [x] 💃🏻 支持插入原生 Emoji、设置常用表情列表;
85 | - [x] 🚑 支持编辑内容保存**本地存储**,防止意外丢失;
86 | - [x] 📝 支持**实时预览**,主窗口大小拖拽,字符计数;
87 | - [x] 🛠 支持常用快捷键(**Tab**),及代码块添加复制
88 | - [x] ✨ 支持**导出**携带样式的 PDF、PNG、JPEG 等;
89 | - [x] ✨ 升级 Vditor,新增对 \`echarts\` 图表的支持;
90 | - [x] 👏 支持检查并格式化 Markdown 语法,使其专业;
91 | - [x] 🦑 支持五线谱、及[部分站点、视频、音频解析](https://github.com/b3log/vditor/issues/117?ref=hacpai.com#issuecomment-526986052);
92 | - [x] 🌟 增加对**所见即所得**编辑模式的支持(\`⌘-⇧-M\`);
93 |
94 | ---
95 |
96 | ### 2. 书写一个质能守恒公式[^LaTeX]
97 |
98 | $$
99 | E=mc^2
100 | $$
101 |
102 | ---
103 |
104 | ### 3. 高亮一段代码[^code]
105 |
106 | \`\`\`js
107 | // 给页面里所有的 DOM 元素添加一个 1px 的描边(outline);
108 | [].forEach.call($$("*"),function(a){
109 | a.style.outline="1px solid #"+(~~(Math.random()*(1<<24))).toString(16);
110 | })
111 | \`\`\`
112 |
113 | ---
114 |
115 | ### 4. 高效绘制[流程图](https://github.com/knsv/mermaid#flowchart)
116 |
117 | \`\`\`mermaid
118 | graph TD
119 | A[用户请求] --> B[语义解析]
120 | B --> C[RAG检索]
121 |
122 | C -->|✅ 知识库匹配| D[上下文增强]
123 | C -->|❌ 无匹配| E[任务分解]
124 |
125 | D --> E
126 |
127 | E --> F{工具选择}
128 |
129 | F -->|🛠️ 核心工具| G{基础操作}
130 | F -->|🔌 MCP扩展服务| H{MCP操作}
131 |
132 | G -->|✏️ 文件操作| I[读写/替换]
133 | G -->|🖥️ 系统命令执行| J[执行命令]
134 | G -->|🔍 代码分析| K[代码分析]
135 |
136 | H -->|⚙️ 使用MCP工具| L[使用MCP工具]
137 | H -->|📦 访问MCP资源| M[访问MCP资源]
138 |
139 | I --> N[结果验证]
140 | J --> N
141 | K --> N
142 | L --> N
143 | M --> N
144 |
145 | N --> O{完成判断}
146 |
147 | O -->|✅| P[提交最终结果]
148 | O -->|❌| E
149 | \`\`\`
150 |
151 | ---
152 |
153 | ### 5. 高效绘制[序列图](https://github.com/knsv/mermaid#sequence-diagram)
154 |
155 | \`\`\`mermaid
156 | sequenceDiagram
157 | participant Alice
158 | participant Bob
159 | Alice->John: Hello John, how are you?
160 | loop Healthcheck
161 | John->John: Fight against hypochondria
162 | end
163 | Note right of John: Rational thoughts
prevail...
164 | John-->Alice: Great!
165 | John->Bob: How about you?
166 | Bob-->John: Jolly good!
167 | \`\`\`
168 |
169 | ---
170 |
171 | ### 6. 高效绘制[甘特图](https://github.com/knsv/mermaid#gantt-diagram)
172 |
173 | >**甘特图**内在思想简单。基本是一条线条图,横轴表示时间,纵轴表示活动(项目),线条表示在整个期间上计划和实际的活动完成情况。它直观地表明任务计划在什么时候进行,及实际进展与计划要求的对比。
174 |
175 | \`\`\`mermaid
176 | gantt
177 | title 项目开发流程
178 | section 项目确定
179 | 需求分析 :a1, 2019-06-22, 3d
180 | 可行性报告 :after a1, 5d
181 | 概念验证 : 5d
182 | section 项目实施
183 | 概要设计 :2019-07-05 , 5d
184 | 详细设计 :2019-07-08, 10d
185 | 编码 :2019-07-15, 10d
186 | 测试 :2019-07-22, 5d
187 | section 发布验收
188 | 发布: 2d
189 | 验收: 3d
190 | \`\`\`
191 |
192 | ### 7. 支持图表
193 |
194 | \`\`\`echarts
195 | ${echartsDemoJsonStr}
196 | \`\`\`
197 |
198 | >**备注**:上述 echarts 图表📈,其数据,须使用严格的 **JSON** 格式;您可使用 JSON.stringify(data),将对象传换从而得标准数据,即可正常使用。
199 |
200 | ---
201 |
202 | ### 8. 绘制表格
203 |
204 | | 作品名称 | 在线地址 | 上线日期 |
205 | | :-------- | :----- | :----: |
206 | | 逍遥自在轩 | [https://niceshare.site](https://niceshare.site/?ref=markdown.lovejade.cn) |2024-04-26|
207 | | 玉桃文飨轩 | [https://share.lovejade.cn](https://share.lovejade.cn/?ref=markdown.lovejade.cn) |2022-08-26|
208 | | 缘知随心庭 | [https://fine.niceshare.site](https://fine.niceshare.site/?ref=markdown.lovejade.cn) |2022-02-26|
209 | | 静轩之别苑 | [http://quickapp.lovejade.cn](http://quickapp.lovejade.cn/?ref=markdown.lovejade.cn) |2019-01-12|
210 | | 晚晴幽草轩 | [https://www.jeffjade.com](https://www.jeffjade.com/?ref=markdown.lovejade.cn) |2014-09-20|
211 |
212 | ---
213 |
214 | ### 9. 更详细语法说明
215 |
216 | 想要查看更详细的语法说明,可以参考这份 [Markdown 资源列表](https://github.com/nicejade/nice-front-end-tutorial/blob/master/tutorial/markdown-tutorial.md),涵盖入门至进阶教程,以及资源、平台等信息,能让您对她有更深的认知。
217 |
218 | 总而言之,不同于其它**所见即所得**的编辑器:你只需使用键盘专注于书写文本内容,就可以生成印刷级的排版格式,省却在键盘和工具栏之间来回切换,调整内容和格式的麻烦。**Markdown 在流畅的书写和印刷级的阅读体验之间找到了平衡。** 目前它已经成为世界上最大的技术分享网站 \`GitHub\` 和 技术问答网站 \`StackOverFlow\` 的御用书写格式,而且越发流行,正在在向各行业渗透。
219 |
220 | 最新更新于 2025.04.16
221 | `
222 |
--------------------------------------------------------------------------------
/src/global.js:
--------------------------------------------------------------------------------
1 | /** @format */
2 |
3 | import Vue from 'vue'
4 |
5 | /* ------------------------Vue Global Config------------------------------ */
6 | Vue.config.productionTip = false
7 |
8 | /* ------------------------- Global Variable ------------------------------- */
9 | import { appTitle } from './config/constant'
10 | window.$appTitle = appTitle
11 |
12 | /* ------------------------Vue Global Variable------------------------------ */
13 | import { $utils, $document, $lodash } from '@helper'
14 | import { Message } from 'element-ui'
15 | Vue.prototype.$_ = $lodash
16 | Vue.prototype.$utils = $utils
17 | Vue.prototype.$document = $document
18 | Vue.prototype.$message = options => Message(options)
19 |
20 | /* ------------------------Vue Global Components------------------------------ */
21 | import { Button, Dropdown, DropdownMenu, DropdownItem, Loading } from 'element-ui'
22 | Vue.use(Button)
23 | Vue.use(Dropdown)
24 | Vue.use(DropdownMenu)
25 | Vue.use(DropdownItem)
26 | Vue.use(Loading)
27 |
28 | import VueMeta from 'vue-meta'
29 | Vue.use(VueMeta)
30 |
31 | import Icon from '@components/Icon'
32 | Vue.component('icon', Icon)
33 |
--------------------------------------------------------------------------------
/src/helper/document.js:
--------------------------------------------------------------------------------
1 | /** @format */
2 |
3 | export default {
4 | toggleClass(el, className) {
5 | if (el.classList) {
6 | el.classList.toggle(className)
7 | } else {
8 | var classes = el.className.split(' ')
9 | var existingIndex = classes.indexOf(className)
10 |
11 | if (existingIndex >= 0) {
12 | classes.splice(existingIndex, 1)
13 | } else {
14 | classes.push(className)
15 | }
16 | el.className = classes.join(' ')
17 | }
18 | },
19 |
20 | addClass(el, className) {
21 | if (el.classList) {
22 | el.classList.add(className)
23 | } else {
24 | el.className += ` ${className}`
25 | }
26 | },
27 |
28 | removeClass(el, className) {
29 | if (el.classList) {
30 | el.classList.remove(className)
31 | } else {
32 | el.className = el.className.replace(
33 | new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'),
34 | ' '
35 | )
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/helper/export.js:
--------------------------------------------------------------------------------
1 | /** @format */
2 | import html2canvas from 'html2canvas'
3 | import canvg from 'canvg'
4 |
5 | let TARGET_WIDTH = 960
6 | let TARGET_HEIGHT = 800
7 |
8 | const MARGIN_WIDTH = 50
9 | const MARGIN_HEIGHT = 80
10 | const RADIUS = 6
11 |
12 | const SHADOW_X = 0
13 | const SHADOW_Y = 40
14 | const SHADOW_BLUR = 50
15 | const SHADOW_COLOR = 'rgba(0, 0, 0, 0.21)'
16 |
17 | function drawRoundedRec(origCanvas, scale) {
18 | const roundCanvas = document.createElement('canvas')
19 | roundCanvas.width = TARGET_WIDTH * scale
20 | roundCanvas.height = TARGET_HEIGHT * scale
21 |
22 | const roundCtx = roundCanvas.getContext('2d')
23 | const roundRadius = RADIUS * scale
24 | const x1 = roundRadius
25 | const y1 = 0
26 | const x2 = x1 + roundCanvas.width - 2 * roundRadius
27 | const y2 = y1
28 | const x3 = x2 + roundRadius
29 | const y3 = roundRadius
30 | const x4 = x3
31 | const y4 = y3 + roundCanvas.height - 2 * roundRadius
32 | const x5 = x2
33 | const y5 = y4 + roundRadius
34 | const x6 = x1
35 | const y6 = y5
36 | const x7 = x6 - roundRadius
37 | const y7 = y4
38 | const x8 = x7
39 | const y8 = y3
40 | roundCtx.beginPath()
41 | roundCtx.moveTo(x1, y1)
42 | roundCtx.lineTo(x2, y2)
43 | roundCtx.quadraticCurveTo(x3, y2, x3, y3)
44 | roundCtx.lineTo(x4, y4)
45 | roundCtx.quadraticCurveTo(x4, y5, x5, y5)
46 | roundCtx.lineTo(x6, y6)
47 | roundCtx.quadraticCurveTo(x7, y6, x7, y7)
48 | roundCtx.lineTo(x8, y8)
49 | roundCtx.quadraticCurveTo(x8, y1, x1, y1)
50 | roundCtx.clip()
51 | roundCtx.drawImage(origCanvas, 0, 0)
52 | return roundCanvas
53 | }
54 |
55 | function drawShadow(origCanvas) {
56 | const bgdCanvas = document.createElement('canvas')
57 | bgdCanvas.width = origCanvas.width + MARGIN_WIDTH
58 | bgdCanvas.height = origCanvas.height + MARGIN_HEIGHT
59 | const ctx = bgdCanvas.getContext('2d')
60 |
61 | ctx.shadowOffsetX = SHADOW_X
62 | ctx.shadowOffsetY = SHADOW_Y
63 | ctx.shadowBlur = SHADOW_BLUR
64 | ctx.shadowColor = SHADOW_COLOR
65 | ctx.drawImage(origCanvas, MARGIN_WIDTH / 2, 0)
66 | return bgdCanvas
67 | }
68 |
69 | /**
70 | * @desc 兼容使用 html2canvas 库不能完整捕获 SVG 问题;
71 | * @param {Dom} targetElem - 所要导出目标 DOM
72 | */
73 | const handleCaptureSvg = (targetElem) => {
74 | const nodesToRecover = []
75 | const nodesToRemove = []
76 | const svgElem = targetElem.querySelectorAll('svg')
77 |
78 | for (let key = 0, len = svgElem.length; key < len; key++) {
79 | const node = svgElem[key]
80 | const parentNode = node.parentNode
81 |
82 | try {
83 | // 获取SVG的XML字符串
84 | const svgXml = new XMLSerializer().serializeToString(node)
85 | // 创建一个新的canvas元素
86 | const canvas = document.createElement('canvas')
87 | // 设置canvas尺寸与SVG相同
88 | const svgRect = node.getBoundingClientRect()
89 | canvas.width = svgRect.width
90 | canvas.height = svgRect.height
91 |
92 | // 使用canvg渲染SVG到canvas
93 | const ctx = canvas.getContext('2d')
94 | canvg(canvas, svgXml, {
95 | ignoreMouse: true,
96 | ignoreAnimation: true,
97 | ignoreDimensions: false,
98 | ignoreClear: true,
99 | })
100 |
101 | // 保存原始节点信息以便恢复
102 | nodesToRecover.push({
103 | parent: parentNode,
104 | child: node,
105 | })
106 |
107 | // 临时移除SVG节点
108 | parentNode.removeChild(node)
109 |
110 | // 添加canvas替代SVG
111 | nodesToRemove.push({
112 | parent: parentNode,
113 | child: canvas,
114 | })
115 | parentNode.appendChild(canvas)
116 | } catch (error) {
117 | console.error('处理SVG时出错:', error)
118 | }
119 | }
120 |
121 | // 返回节点信息以便后续恢复
122 | return { nodesToRecover, nodesToRemove }
123 | }
124 |
125 | export const generateScreenshot = async (targetDom) => {
126 | handleCaptureSvg(targetDom)
127 | const domStyleObj = getComputedStyle(targetDom)
128 | TARGET_WIDTH = +domStyleObj.width.replace(`px`, '')
129 | TARGET_HEIGHT = +domStyleObj.height.replace(`px`, '')
130 |
131 | const scale = window.devicePixelRatio
132 | const options = {
133 | scale,
134 | allowTaint: true,
135 | useCORS: true, // 启用CORS支持
136 | backgroundColor: '#fefefe',
137 | imageTimeout: 0, // 禁用图像超时
138 | logging: false,
139 | }
140 | const origCanvas = await html2canvas(targetDom, options)
141 | const roundCanvas = drawRoundedRec(origCanvas, scale)
142 | return drawShadow(roundCanvas)
143 | }
144 |
--------------------------------------------------------------------------------
/src/helper/index.js:
--------------------------------------------------------------------------------
1 | /** @format */
2 |
3 | export const $utils = require('./utils').default
4 | export const $lodash = require('./lodash').default
5 | export const $document = require('./document').default
6 |
--------------------------------------------------------------------------------
/src/helper/lodash.js:
--------------------------------------------------------------------------------
1 | /**
2 | * /*
3 | * https://www.npmjs.com/package/lodash-webpack-plugin
4 | * https://www.npmjs.com/package/babel-plugin-lodash
5 | *
6 | * @format
7 | * @date: 2017-08-01
8 | * @lastModify: 2018-05-16
9 | * @desc: Modular Lodash builds without the hassle. You can freely add the method you need
10 | * @detail:
11 | */
12 |
13 | import _ from 'lodash'
14 |
15 | export default {
16 | clone: _.clone,
17 | cloneDeep: _.cloneDeep,
18 | endsWith: _.endsWith,
19 | debounce: _.debounce,
20 | throttle: _.throttle,
21 | find: _.find,
22 | isEmpty: _.isEmpty,
23 | flatten: _.flatten,
24 | flattenDepth: _.flattenDepth
25 | }
26 |
--------------------------------------------------------------------------------
/src/helper/utils.js:
--------------------------------------------------------------------------------
1 | /** @format */
2 |
3 | import Vue from 'vue'
4 | const $lodash = require('./lodash').default
5 |
6 | if (typeof String.prototype.startsWith !== 'function') {
7 | Window.String.prototype.startsWith = function (prefix) {
8 | return this.slice(0, prefix.length) === prefix
9 | }
10 | }
11 |
12 | export default {
13 | resMsg(res) {
14 | let key = {
15 | zh: 'Chinese',
16 | en: 'English',
17 | }[Vue.config.lang]
18 | try {
19 | let obj = JSON.parse(res.Message)
20 | return obj[key] || obj.Chinese
21 | } catch (e) {
22 | return res && res.Message
23 | }
24 | },
25 |
26 | serverUrl(apiName) {
27 | return `app/${apiName}`
28 | },
29 |
30 | titleLang(zhStr, enStr) {
31 | return {
32 | zh: zhStr,
33 | en: enStr,
34 | }
35 | },
36 |
37 | query(search) {
38 | let str = search || window.location.search
39 | let objURL = {}
40 |
41 | str.replace(new RegExp('([^?=&]+)(=([^&]*))?', 'g'), ($0, $1, $2, $3) => {
42 | objURL[$1] = $3
43 | })
44 | return objURL
45 | },
46 |
47 | queryString(url, query) {
48 | let str = []
49 | for (let key in query) {
50 | str.push(key + '=' + query[key])
51 | }
52 | let paramStr = str.join('&')
53 | return paramStr ? `${url}?${paramStr}` : url
54 | },
55 |
56 | assembleExternalLink(url) {
57 | const separator = $lodash.endsWith(url, '/') ? '' : '/'
58 | return `${url}${separator}?utm_source=markdown.lovejade.cn`
59 | },
60 |
61 | openAuthorSite(p) {
62 | window.open(`${this.assembleExternalLink('https://aboutme.lovejade.cn/')}&position=${p}`)
63 | },
64 |
65 | makeUpZero(num = 0) {
66 | return num < 10 ? `0${num}` : num
67 | },
68 |
69 | getTimestamp() {
70 | const date = new Date()
71 | const y = `${date.getFullYear()}`.replace('20', '')
72 | let mo = this.makeUpZero(date.getMonth() + 1)
73 | const d = this.makeUpZero(date.getDate())
74 | const h = this.makeUpZero(date.getHours())
75 | const m = this.makeUpZero(date.getMinutes())
76 | const s = this.makeUpZero(date.getSeconds())
77 | return `${y}-${mo}-${d}-${h}${m}${s}`
78 | },
79 |
80 | getExportFileName() {
81 | const type = location.pathname.split('/')[0]
82 | const timestamp = this.getTimestamp()
83 | const filename = `arya-${timestamp}.${type}`
84 | return filename
85 | },
86 |
87 | updateHtmlStyle() {
88 | const htmlNode = document.querySelector('html')
89 | htmlNode.style.overflow = 'auto'
90 | htmlNode.style.height = 'auto'
91 | },
92 |
93 | hideVditorTextarea() {
94 | const exportVditorNode = document.getElementById('khaleesi')
95 | const option = {
96 | childList: true, // 子节点的变动(新增、删除或者更改)
97 | attributes: true, // 属性的变动
98 | characterData: true, // 节点内容或节点文本的变动
99 |
100 | subtree: true, // 是否将观察器应用于该节点的所有后代节点
101 | attributeFilter: ['class', 'style'], // 观察特定属性
102 | attributeOldValue: true, // 观察 attributes 变动时,是否需要记录变动前的属性值
103 | characterDataOldValue: true, // 观察 characterData 变动,是否需要记录变动前的值
104 | }
105 | const mutationObserver = new MutationObserver(() => {
106 | const vditorTextarea = document.getElementsByClassName('vditor-textarea')
107 | if (vditorTextarea && vditorTextarea[0]) {
108 | vditorTextarea[0].style.display = 'none'
109 | mutationObserver.disconnect()
110 | }
111 | })
112 | mutationObserver.observe(exportVditorNode, option)
113 | },
114 |
115 | /* -----------------------------localStorage------------------------------------ */
116 | /*
117 | * set localStorage
118 | */
119 | setStorage(name, content) {
120 | if (!name) return
121 | if (typeof content !== 'string') {
122 | content = JSON.stringify(content)
123 | }
124 | window.localStorage.setItem(name, content)
125 | },
126 |
127 | /**
128 | * get localStorage
129 | */
130 | getStorage(name) {
131 | if (!name) return
132 | let content = window.localStorage.getItem(name)
133 | return JSON.parse(content)
134 | },
135 |
136 | /**
137 | * delete localStorage
138 | */
139 | removeStorage(name) {
140 | if (!name) return
141 | window.localStorage.removeItem(name)
142 | },
143 | }
144 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | /** @format */
2 |
3 | import Vue from 'vue'
4 | import './global.js'
5 | import App from './App.vue'
6 | import router from './router'
7 | import './registerServiceWorker'
8 |
9 | const updateCanonical = (url) => {
10 | let link = document.querySelector("link[rel='canonical']")
11 | if (!link) {
12 | link = document.createElement('link')
13 | link.setAttribute('rel', 'canonical')
14 | document.head.appendChild(link)
15 | }
16 | link.setAttribute('href', url)
17 | }
18 |
19 | router.beforeEach((to, _, next) => {
20 | const canonicalUrl = `${to.path}`
21 | updateCanonical(canonicalUrl)
22 | next()
23 | })
24 |
25 | new Vue({
26 | router,
27 | render: (h) => h(App),
28 | }).$mount('#app')
29 |
--------------------------------------------------------------------------------
/src/mixins/metaMixin.js:
--------------------------------------------------------------------------------
1 | /** @format */
2 |
3 | export default {
4 | data() {
5 | const vm = this
6 | return {
7 | title: '首页',
8 | siteTitle: '在线 Markdown 编辑器',
9 | titleTemplate: '%s - ' + vm.siteTitle,
10 | keywords:
11 | 'vue,vue-cli3,webpack,vuex,vue-router,element-ui,TypeScript,ESLint,Prettier,Dayjs,Markdown,Jest,PWA,开箱即用,脚手架,模板',
12 | description:
13 | '此为基于 Vue-Cli3 搭建的开箱即用 Vue 脚手架模版,致力于探究更高效地构建优质 Web 应用。'
14 | }
15 | },
16 |
17 | created() {},
18 |
19 | metaInfo() {
20 | const titleContent = this.title ? `${this.title} - ${this.siteTitle}` : `${this.siteTitle}`
21 | return {
22 | title: this.title,
23 | titleTemplate: titleChunk => {
24 | return titleChunk ? `${titleChunk} - ${this.siteTitle}` : `${this.siteTitle}`
25 | },
26 | meta: [
27 | { vmid: 'title', name: 'title', content: titleContent },
28 | { vmid: 'keywords', name: 'keywords', content: this.keywords },
29 | { vmid: 'description', name: 'description', content: this.description },
30 | { vmid: 'og:type', property: 'og:type', content: 'website' },
31 | { vmid: 'og:title', property: 'og:title', content: titleContent },
32 | {
33 | vmid: 'og:image',
34 | property: 'og:image',
35 | content: 'https://nice.lovejade.cn/logo.png'
36 | },
37 | {
38 | vmid: 'og:keywords',
39 | property: 'og:keywords',
40 | content: this.keywords
41 | },
42 | {
43 | vmid: 'og:description',
44 | property: 'og:description',
45 | content: this.description
46 | }
47 | ]
48 | }
49 | },
50 |
51 | mounted() {},
52 |
53 | methods: {}
54 | }
55 |
--------------------------------------------------------------------------------
/src/pages/About.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
36 |
--------------------------------------------------------------------------------
/src/pages/ExportImage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 返回主页
6 |
7 | {{ isExporting ? '正在导出...' : '生成导出' }}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
73 |
--------------------------------------------------------------------------------
/src/pages/ExportPPT.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{ savedMdContent }}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
78 |
79 |
94 |
--------------------------------------------------------------------------------
/src/pages/ExportPdf.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 返回主页
7 |
8 | {{ exporting ? '正在导出...' : '生成导出' }}
9 |
10 |
11 |
12 |
13 |
14 |
15 |
92 |
--------------------------------------------------------------------------------
/src/pages/Main.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
122 |
123 |
174 |
--------------------------------------------------------------------------------
/src/pages/partials/Frame.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
28 |
29 |
43 |
--------------------------------------------------------------------------------
/src/pages/partials/NotFound.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 4
8 | 0
9 | 4
10 |
11 |
YOU LOOK LOST
12 |
16 |
17 |
18 |
19 |
20 |
34 |
35 |
156 |
--------------------------------------------------------------------------------
/src/registerServiceWorker.js:
--------------------------------------------------------------------------------
1 | /**
2 | * /* eslint-disable no-console
3 | *
4 | * @format
5 | */
6 |
7 | import { register } from 'register-service-worker'
8 |
9 | if (process.env.NODE_ENV === 'production') {
10 | register(`${process.env.BASE_URL}service-worker.js`, {
11 | ready() {
12 | console.log(
13 | 'App is being served from cache by a service worker.\n' +
14 | 'For more details, visit https://goo.gl/AFskqB'
15 | )
16 | },
17 | cached() {
18 | console.log('Content has been cached for offline use.')
19 | },
20 | updated() {
21 | console.log('New content is available; please refresh.')
22 | },
23 | offline() {
24 | console.log('No internet connection found. App is running in offline mode.')
25 | },
26 | error(error) {
27 | console.error('Error during service worker registration:', error)
28 | }
29 | })
30 | }
31 |
--------------------------------------------------------------------------------
/src/router/beforeEachHooks.js:
--------------------------------------------------------------------------------
1 | /** @format */
2 |
3 | export default {
4 | updatePageMeta(to, from, next) {
5 | if (to.meta.title) {
6 | document.title = to.meta.title
7 | }
8 | next()
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/router/commonRoutes.js:
--------------------------------------------------------------------------------
1 | /** @format */
2 |
3 | import Frame from '@pages/partials/Frame'
4 | import NotFound from '@pages/partials/NotFound'
5 |
6 | export default [
7 | {
8 | path: '/',
9 | meta: {
10 | title: window.$appTitle
11 | },
12 | component: resolve => require(['@pages/Main'], resolve)
13 | },
14 | {
15 | path: '/about-arya',
16 | meta: {
17 | title: `关于 | ${window.$appTitle}`
18 | },
19 | component: Frame,
20 | children: [
21 | {
22 | path: '/',
23 | meta: {
24 | title: `关于 | ${window.$appTitle}`
25 | },
26 | component: resolve => require(['@pages/About'], resolve)
27 | }
28 | ]
29 | },
30 | {
31 | path: '/index',
32 | redirect: '/'
33 | },
34 | {
35 | path: '*',
36 | meta: {
37 | title: 'Page Not Found'
38 | },
39 | component: NotFound
40 | }
41 | ]
42 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | /** @format */
2 |
3 | import Vue from 'vue'
4 | import Router from 'vue-router'
5 | import beforeEachHooks from './beforeEachHooks'
6 | import RoutesMapConfig from './routes'
7 | import commonRoutesMap from './commonRoutes'
8 |
9 | Vue.use(Router)
10 |
11 | const routerInstance = new Router({
12 | mode: 'history',
13 | /* ~~~~~~~~~~~~~~~~~~~~~~~~@CHANGE@~~~~~~~~~~~~~~~~~~~~~~~~ */
14 | /*
15 | @desc: base,应用的基路径;如整个单页应用服务在 /app/ 下,base 就应该设为 "/app/";
16 | @reference: https://router.vuejs.org/zh-cn/api/options.html#base
17 | */
18 | base: '/',
19 | linkActiveClass: 'active',
20 | scrollBehavior: () => ({ y: 0 }),
21 | routes: RoutesMapConfig.concat(commonRoutesMap)
22 | })
23 |
24 | Object.values(beforeEachHooks).forEach(hook => {
25 | routerInstance.beforeEach(hook)
26 | })
27 |
28 | export default routerInstance
29 |
--------------------------------------------------------------------------------
/src/router/routes/index.js:
--------------------------------------------------------------------------------
1 | /** @format */
2 |
3 | const files = require.context('.', true, /\.js$/)
4 |
5 | var configArray = []
6 |
7 | files.keys().forEach(key => {
8 | if (key === './index.js') return
9 | configArray = configArray.concat(files(key).default)
10 | })
11 | export default configArray
12 |
--------------------------------------------------------------------------------
/src/router/routes/main.js:
--------------------------------------------------------------------------------
1 | /** @format */
2 |
3 | import Frame from '@pages/partials/Frame'
4 |
5 | export default [
6 | {
7 | path: '/export',
8 | component: Frame,
9 | meta: {
10 | title: window.$appTitle,
11 | },
12 | children: [
13 | {
14 | path: 'png',
15 | meta: {
16 | title: `导出 PNG | ${window.$appTitle}`,
17 | },
18 | component: (resolve) => require(['@pages/ExportImage'], resolve),
19 | },
20 | {
21 | path: 'pdf',
22 | meta: {
23 | title: `导出 PDF | ${window.$appTitle}`,
24 | },
25 | component: (resolve) => require(['@pages/ExportPdf'], resolve),
26 | },
27 | {
28 | path: 'ppt',
29 | meta: {
30 | title: `PPT 预览 | ${window.$appTitle}`,
31 | },
32 | component: (resolve) => require(['@pages/ExportPPT'], resolve),
33 | },
34 | ],
35 | },
36 | ]
37 |
--------------------------------------------------------------------------------
/tests/unit/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | jest: true
4 | },
5 | rules: {
6 | 'import/no-extraneous-dependencies': 'off'
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/tests/unit/Arrow.spec.js:
--------------------------------------------------------------------------------
1 | /** @format */
2 |
3 | import { shallowMount } from '@vue/test-utils'
4 | import Arrow from '@/components/icons/Arrow.vue'
5 |
6 | describe('Arrow.vue', () => {
7 | // ------------------------Test [props.direction]------------------------Start
8 | it('renders props.direction when passed', () => {
9 | const parpDirection = 'right'
10 | const wrapper = shallowMount(Arrow, {
11 | propsData: { direction: parpDirection }
12 | })
13 | expect(wrapper.classes()).toContain(parpDirection)
14 | })
15 |
16 | it('renders props.direction when NOT passed', () => {
17 | // direction default Value is [left]
18 | const parpDirection = '~~left'
19 | const defaultDirection = 'left'
20 | const wrapper = shallowMount(Arrow, {
21 | propsData: { direction: parpDirection }
22 | })
23 | expect(wrapper.classes()).toContain(defaultDirection)
24 | /* const compClassListStr = wrapper
25 | .find('.arrow-component')
26 | .element.classList.toString()
27 | expect(compClassListStr).toBe(`arrow-component left`) */
28 | })
29 |
30 | // ------------------------Test [props.color]------------------------Start
31 | it('renders props.color when passed', () => {
32 | // color default Vaule is [#479537]
33 | const propColor = '#666666'
34 | const wrapper = shallowMount(Arrow, {
35 | propsData: { color: propColor }
36 | })
37 | const compBorderColor = wrapper.find('.arrow-component').element.style
38 | .borderColor
39 | expect(compBorderColor).toBe(propColor)
40 | })
41 |
42 | it('renders props.color when Not passed', () => {
43 | // color default Vaule is [#479537]
44 | const propColor = '#666 666#'
45 | const defaultColor = '#479537'
46 | const wrapper = shallowMount(Arrow, {
47 | propsData: { color: propColor }
48 | })
49 | const compBorderColor = wrapper.find('.arrow-component').element.style
50 | .borderColor
51 | expect(compBorderColor).toBe(defaultColor)
52 | })
53 | })
54 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | /** @format */
2 |
3 | const path = require('path')
4 | const SizePlugin = require('size-plugin')
5 |
6 | const isProductionEnvFlag = process.env.NODE_ENV === 'production'
7 |
8 | function resolveRealPath(dir) {
9 | return path.join(__dirname, dir)
10 | }
11 |
12 | // https://github.com/vuejs/vue-docs-zh-cn/blob/master/vue-cli/config.md
13 | module.exports = {
14 | // Project deployment base
15 | // By default we assume your app will be deployed at the root of a domain,
16 | // e.g. https://www.my-app.com/
17 | // If your app is deployed at a sub-path, you will need to specify that
18 | // sub-path here. For example, if your app is deployed at
19 | // https://www.foobar.com/my-app/
20 | // then change this to '/my-app/'
21 | publicPath: '/',
22 |
23 | // where to output built files
24 | outputDir: 'dist',
25 |
26 | // whether to use eslint-loader for lint on save.
27 | // valid values: true | false | 'error'
28 | // when set to 'error', lint errors will cause compilation to fail.
29 | lintOnSave: true,
30 |
31 | // https://cli.vuejs.org/config/#runtimecompiler
32 | runtimeCompiler: false,
33 |
34 | // babel-loader skips `node_modules` deps by default.
35 | // explicitly transpile a dependency with this option.
36 | transpileDependencies: [
37 | /* string or regex */
38 | ],
39 |
40 | // generate sourceMap for production build?
41 | productionSourceMap: process.env.NODE_ENV !== 'production',
42 |
43 | // tweak internal webpack configuration.
44 | // see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
45 | chainWebpack: (config) => {
46 | config.resolve.alias
47 | .set('vue$', 'vue/dist/vue.esm.js')
48 | .set('@helper', resolveRealPath('src/helper'))
49 | .set('@config', resolveRealPath('src/config'))
50 | .set('@pages', resolveRealPath('src/pages'))
51 | .set('@assets', resolveRealPath('src/assets'))
52 | .set('@router', resolveRealPath('src/router'))
53 | .set('@mixins', resolveRealPath('src/mixins'))
54 | .set('@components', resolveRealPath('src/components'))
55 |
56 | // remove the old loader & add new one
57 | config.module.rules.delete('svg')
58 | config.module
59 | .rule('svg')
60 | .test(/\.svg$/)
61 | .use('svg-sprite-loader')
62 | .loader('svg-sprite-loader')
63 | .options({
64 | name: '[name]-[hash:7]',
65 | prefixize: true,
66 | })
67 |
68 | const splitOptions = config.optimization.get('splitChunks')
69 | config.optimization.splitChunks(
70 | Object.assign({}, splitOptions, {
71 | // (缺省值5)按需加载时的最大并行请求数
72 | maxAsyncRequests: 16,
73 | // (默认值3)入口点上的最大并行请求数
74 | maxInitialRequests: 16,
75 | // (默认值:1)分割前共享模块的最小块数
76 | minChunks: 1,
77 | // (默认值:30000)块的最小大小
78 | minSize: 30000,
79 | // webpack 将使用块的起源和名称来生成名称: `vendors~main.js`,如项目与"~"冲突,则可通过此值修改,Eg: '-'
80 | automaticNameDelimiter: '~',
81 | // cacheGroups is an object where keys are the cache group names.
82 | name: true,
83 | cacheGroups: {
84 | default: false,
85 | common: {
86 | name: `chunk-common`,
87 | minChunks: 2,
88 | priority: -20,
89 | chunks: 'initial',
90 | reuseExistingChunk: true,
91 | },
92 | element: {
93 | name: 'element',
94 | test: /[\\/]node_modules[\\/]element-ui[\\/]/,
95 | chunks: 'initial',
96 | // 默认组的优先级为负数,以允许任何自定义缓存组具有更高的优先级(默认值为0)
97 | priority: -30,
98 | },
99 | },
100 | })
101 | )
102 |
103 | // https://github.com/webpack-contrib/webpack-bundle-analyzer
104 | if (process.env.npm_config_report) {
105 | config
106 | .plugin('webpack-bundle-analyzer')
107 | .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
108 | }
109 | },
110 |
111 | configureWebpack: {
112 | plugins: [isProductionEnvFlag ? new SizePlugin() : () => {}],
113 | },
114 |
115 | // use thread-loader for babel & TS in production build
116 | // enabled by default if the machine has more than 1 cores
117 | parallel: require('os').cpus().length > 1,
118 |
119 | // options for the PWA plugin.
120 | // see => https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa
121 | // https://developers.google.com/web/tools/workbox/modules/workbox-webpack-plugin
122 | pwa: {
123 | name: 'Arya - 在线 Markdown 编辑器',
124 | themeColor: '#4DBA87',
125 | msTileColor: '#000000',
126 | appleMobileWebAppCapable: 'yes',
127 | appleMobileWebAppStatusBarStyle: 'black',
128 | iconPaths: {
129 | favicon32: 'img/icons/favicon-32x32.png',
130 | favicon16: 'img/icons/favicon-16x16.png',
131 | appleTouchIcon: 'img/icons/apple-touch-icon.png',
132 | maskIcon: 'img/icons/safari-pinned-tab.svg',
133 | msTileImage: 'img/icons/mstile-150x150.png',
134 | },
135 | // configure the workbox plugin (GenerateSW or InjectManifest)
136 | workboxPluginMode: 'InjectManifest',
137 | workboxOptions: {
138 | // swSrc is required in InjectManifest mode.
139 | swSrc: 'public/service-worker.js',
140 | // ...other Workbox options...
141 | },
142 | },
143 |
144 | // configure webpack-dev-server behavior
145 | devServer: {
146 | open: process.platform === 'darwin',
147 | host: '0.0.0.0',
148 | port: 8080,
149 | https: false,
150 | hotOnly: false,
151 | // See https://github.com/vuejs/vue-cli/blob/dev/docs/cli-service.md#configuring-proxy
152 | proxy: null, // string | Object
153 | before: () => {},
154 | },
155 |
156 | // options for 3rd party plugins
157 | pluginOptions: {},
158 | }
159 |
--------------------------------------------------------------------------------