提交 ed622516 编写于 作者: 璃白.'s avatar 璃白. 🌻

feat:添加help doc

上级 d9a2875b
无法预览此类型文件
......@@ -81,7 +81,7 @@ void main()
// aaa.remove()
// })
// `,
value: "abcabcabc123**中文的**字体",
value: "## edswgdfgdfgdfg\n**dfgdfgdfg**\n_ergdfgdfg_\n> ergergdfg\n```\nwefgdfsfdgdf\n```\n- efwefsdfsdf\n\n\nsdgfdfgdfgdfg\n\n\nedrfgdfgdfg\n\n\n\nergergergergerg\nergergergerg",
themeOptions: {
dark: false,
borderColorActive: "#409eff",
......@@ -89,6 +89,7 @@ void main()
textColorActive: "#000",
codeTheme: "atom-one-dark"
},
height: 400,
toolsOptions: {
format: true,
bold: true,
......@@ -124,7 +125,7 @@ void main()
console.log(res);
},
onInput: function(res) {
// console.log("input", res);
console.log("input", res);
},
onChange: function(res) {
// console.log("change", res);
......@@ -147,9 +148,8 @@ void main()
}
});
document.querySelector("#a").onclick = function() {
ee.focus();
};
ee.focus();
document.querySelector("#a").onclick = function() {};
document.querySelector("#b").onclick = function() {
ee.setValue("");
};
......
此差异已折叠。
{
"name": "markdown-editor",
"description": " A open source markdown editor of csdn codechina team contributed",
"version": "0.5.3",
"version": "0.6.1",
"publisher": "guoweijia",
"scripts": {
"start": "webpack serve --mode=development",
......
......@@ -16,7 +16,9 @@
:tabSize="tabSize"
:fullScreen.sync="fullScreen"
:themeOptions="themeOptions"
@upload="$refs.mdUploadFile.click()"
@upload="handleUpload"
@getFormatType="formatType = $event"
@updateShowHelp="showHelp = $event"
/>
<input
ref="mdUploadFile"
......@@ -51,11 +53,14 @@
:height="textareaHeight"
:html.sync="html"
:id="textareaId"
:show-help="showHelp"
:formatType="formatType"
:ref="'md_textarea' + id"
@tab="$refs['md_header' + id].tab()"
@submit="submit"
@enter="handleEnter"
@getFilteredTags="filteredTags = $event"
@updateShowHelp="showHelp = $event"
v-else
/>
<div v-if="maxLength && showWordLimit && !showPreview" class="word_limit">
......@@ -170,6 +175,10 @@ export default {
}
},
computed: {
// isMobile() {
// const isMobile = checkBoswer();
// return isMobile;
// },
textareaId() {
return "textarea_" + this.id;
},
......@@ -192,7 +201,9 @@ export default {
text: "",
html: "",
ulNum: 1,
formatType: "",
htmlMinHeight: 150,
showHelp: false,
textLength: "",
selectionInfo: {
selectorId: "",
......@@ -208,6 +219,10 @@ export default {
html: this.html
});
}, 0);
// if(this.isMobile) {
// }
},
watch: {
focus: {
......@@ -255,9 +270,11 @@ export default {
text: this.text,
html: this.html
};
if (this.filePathRule) {
const checkResult = checktUrl(val, this.filePathRule);
emitContent.invalidList = checkResult;
console.log(checkResult);
}
emitContent.filteredTags = this.filteredTags;
this.$emit("change", emitContent);
......@@ -271,6 +288,7 @@ export default {
html: this.html
};
if (val) {
this.showHelp = false;
this.$emit("focus", value);
} else {
this.$emit("blur", value);
......@@ -309,6 +327,10 @@ export default {
}
},
methods: {
handleUpload() {
this.$refs.mdUploadFile.click();
document.getElementById(this.textareaId).focus();
},
handleEnter() {
this.$refs[this.headId].resetUlNum();
},
......@@ -335,6 +357,7 @@ export default {
box-sizing: border-box;
transition: border 0.3s;
position: relative;
overflow: hidden;
&.fullScreen {
position: fixed;
top: 0;
......
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" id="bold"><path d="M4 2h3.963c.63 0 1.216.05 1.76.148.555.086 1.036.24 1.444.461.407.222.728.53.963.923.234.382.351.868.351 1.459 0 .258-.043.523-.13.794-.073.258-.197.51-.37.757-.16.233-.37.443-.63.627-.258.185-.56.32-.907.406v.074c.852.173 1.488.486 1.908.942.432.443.648 1.064.648 1.864 0 .616-.123 1.151-.37 1.607a3.068 3.068 0 0 1-1 1.107c-.42.283-.914.492-1.482.628A7.806 7.806 0 0 1 8.333 14H4V2zm3.889 4.726c.518 0 .895-.117 1.13-.35.234-.234.351-.536.351-.905 0-.37-.117-.634-.351-.794-.235-.16-.612-.24-1.13-.24H7v2.29h.889zm.222 4.837c.63 0 1.08-.117 1.352-.35.284-.234.426-.573.426-1.016 0-.443-.142-.763-.426-.96-.272-.197-.722-.295-1.352-.295H7v2.621h1.111z"></path></svg>
\ No newline at end of file
<svg t="1626417405941" class="icon" viewBox="0 0 1143 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2471" width="48" height="48"><path d="M387.907832 290.329177a2337.050694 2337.050694 0 0 1-283.603386 107.19739L550.653905 934.120512a38.109783 38.109783 0 0 0 53.659694 5.060971 37.378787 37.378787 0 0 0 6.096966-6.584963L784.986571 698.201855z m71.097595-34.817802l371.957882 380.859832 80.183544-107.501388a38.109783 38.109783 0 0 0-2.316987-48.415724l-75.183572-83.599524-28.719837-31.70682 233.783669-167.015049a67.074618 67.074618 0 1 0-93.537467-93.843466l-165.979055 232.077679-31.768819-35.366799q-66.219623-73.72058-131.892249-147.746159c7.133959 7.987955 5.670968 7.682956 4.939971 7.804956-4.573974 0-8.902949 0.975994-6.097965-1.036994a1211.361103 1211.361103 0 0 1-155.491115 95.489456zM883.037013 59.959489a143.478183 143.478183 0 1 1 200.18586 200.18686l-164.331065 117.379332q22.86587 25.183857 46.768734 51.891704a114.269349 114.269349 0 0 1 6.889961 145.002175L671.631216 978.023262a114.453348 114.453348 0 0 1-160.064089 23.293867 116.587336 116.587336 0 0 1-19.511888-18.293896L8.875989 402.038541a38.049783 38.049783 0 0 1 18.597895-60.976653q350.128007-102.074419 541.899914-242.564619c25.182857-18.293896 81.952533-19.817887 103.233413 4.145977q46.097738 51.890705 99.879431 112.075362l110.550371-154.759119z" p-id="2472"></path></svg>
\ No newline at end of file
......@@ -203,8 +203,6 @@ export function copyFormatRules(selection) {
const end2 = selection.slice(-2);
const end3 = selection.slice(-3);
let formatType = "";
console.log(first6);
switch (true) {
// 斜体
case first1 === "_" && end1 === "_":
......@@ -224,7 +222,8 @@ export function copyFormatRules(selection) {
case first3 === "```" && end3 === "```":
formatType = {
startStr: "\n```\n",
endStr: "\n\n```"
endStr: "\n\n```",
type: "code"
};
break;
// 引用
......
......@@ -29,6 +29,20 @@ textarea {
padding: 0;
}
/* 可以设置不同的进入和离开动画 */
/* 设置持续时间和动画函数 */
.slide-fade-enter-active {
transition: all 0.3s ease;
}
.slide-fade-leave-active {
transition: all 0.3s cubic-bezier(1, 0.5, 0.8, 1);
}
.slide-fade-enter, .slide-fade-leave-to
/* .slide-fade-leave-active for below version 2.1.8 */ {
transform: translateX(40px);
opacity: 0;
}
// img {
// display: block;
// margin: 0;
......
@font-face {
font-family: "iconfont"; /* Project id */
src: url('./font/iconfont.ttf') format('truetype');
src: url('font/iconfont.ttf?t=1626660749010') format('truetype');
}
.iconfont {
......@@ -19,10 +19,6 @@
content: "\e63f";
}
.icon-youxuliebiao:before {
content: "\e6f0";
}
.icon-bold:before {
content: "\e678";
}
......@@ -55,15 +51,59 @@
content: "\e7ed";
}
.icon-yinyong:before {
content: "\e697";
}
.icon-quxiaoquanping_o:before {
content: "\eb98";
}
.icon-yulan:before {
content: "\e668";
}
.icon-daimakuai:before {
content: "\e6af";
}
.icon-yijibiaoti:before {
content: "\e66e";
}
.icon-erjibiaoti:before {
content: "\e66f";
}
.icon-shanchuxian:before {
content: "\e7ae";
}
.icon-geshishua:before {
content: "\e6bb";
content: "\e63d";
}
.icon-yinyong:before {
content: "\e697";
.icon-fengexian:before {
content: "\e60a";
}
.icon-bianji:before {
content: "\e604";
}
.icon-youxuliebiao:before {
content: "\e7a3";
}
.icon-sanjibiaoti:before {
content: "\e602";
}
.icon-guanbi:before {
content: "\e692";
}
.icon-help:before {
content: "\e503";
}
<template>
<div class="help_doc">
<div class="container">
<h2>
Markdown 语法
<span
@click="$emit('updateShowHelp', false)"
:class="['icon iconfont', `icon-guanbi`]"
></span>
</h2>
<ul class="list">
<li v-for="(item, index) in list" :key="index">
<span :class="['icon iconfont', `icon-${item.icon}`]"></span>
<span>{{ item.title }}</span>
<span class="doc">{{ item.doc }}</span>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
props: {
showHelp: {
type: Boolean,
default: false
}
},
data() {
return {
list: [
{
title: "一级标题",
doc: "# 标题",
icon: "yijibiaoti"
},
{
title: "二级标题",
doc: "## 标题",
icon: "erjibiaoti"
},
{
title: "三级标题",
doc: "### 标题",
icon: "sanjibiaoti"
},
{
title: "粗体",
doc: "**内容**",
icon: "bold"
},
{
title: "斜体",
doc: "_内容_",
icon: "italic"
},
{
title: "引用",
doc: "> 引用内容",
icon: "yinyong"
},
{
title: "链接",
doc: "[链接标题](url)",
icon: "lianjie"
},
{
title: "图片",
doc: '![alt](url "title")',
icon: "tupian"
},
{
title: "代码",
doc: "`代码`",
icon: "daimakuai"
},
{
title: "代码块",
doc: "```编程语言↵代码```",
icon: "code"
},
{
title: "无序列表",
doc: "- 内容",
icon: "unorderedList"
},
{
title: "有序列表",
doc: "1. 内容",
icon: "youxuliebiao"
},
{
title: "任务列表",
doc: "- [ ] 待办事项",
icon: "renwu"
},
{
title: "分割线",
doc: "---",
icon: "fengexian"
},
{
title: "删除线",
doc: "~~内容~~",
icon: "shanchuxian"
}
]
};
}
};
</script>
<style lang="less" scoped>
.help_doc {
position: absolute;
// background: #fff;
background: var(--md-editor-content-bg-color);
height: calc(100% + 10px);
width: 260px;
top: 0;
right: -16px;
box-sizing: border-box;
border-left: 1px solid var(--md-editor-border-color);
padding: 14px;
padding-right: 0;
// border-radius: 4px;
z-index: 9;
.container {
overflow-y: auto;
padding-right: 14px;
height: 100%;
scrollbar-color: transparent transparent;
&::-webkit-scrollbar {
display: none;
}
h2 {
font-size: 18px;
color: #333;
.icon {
float: right;
margin-top: 4px;
cursor: pointer;
font-weight: 400;
}
}
ul.list {
margin-top: 10px;
li {
font-size: 14px;
color: #666;
margin-bottom: 10px;
.icon {
display: inline-block;
vertical-align: middle;
}
.doc {
float: right;
}
}
}
}
}
</style>
......@@ -15,9 +15,22 @@
:placeholder="placeholder"
:maxlength="maxLength"
:rows="rows"
:style="{ height: editorHeight, overflow: editorOverFlow }"
:style="{
height: editorHeight,
overflow: editorOverFlow,
cursor: formatType
? `url(https://codechina.csdn.net/codechina/operation-work/uploads/a1b7c2a995b2320dca911e2f2ecb9b88/format.png),text`
: 'text'
}"
>
</textarea>
<transition name="slide-fade">
<helpDoc
v-if="showHelp"
@updateShowHelp="$emit('updateShowHelp', $event)"
:showHelp.sync="showHelp"
/>
</transition>
</div>
</template>
<script>
......@@ -28,7 +41,9 @@ import {
throttle as throttleFn
} from "@/assets/js/utils";
import marked from "marked";
import helpDoc from "./help-doc";
export default {
components: { helpDoc },
props: {
id: {
type: String,
......@@ -80,6 +95,13 @@ export default {
selectionInfo: {
type: Object,
default: () => {}
},
formatType: {
default: ""
},
showHelp: {
type: Boolean,
default: false
}
},
......@@ -139,6 +161,10 @@ export default {
document.removeEventListener("mouseup", this.checkSelection);
},
computed: {
formatIcon() {
return import("@/assets/img/icon-format.png");
return require("@/assets/img/icon-format.png");
},
emitText() {
// return throttleFn(() => {}, this.throttleTime);
return () => {
......@@ -194,8 +220,6 @@ export default {
this.emitText();
},
reSizeTextareaHeight() {
console.log("setHeight");
const textEl = document.getElementById(this.id);
if (!textEl) return;
const fontSize = getComputedStyle(textEl).getPropertyValue("font-size");
......
......@@ -52,7 +52,7 @@ export default {
</script>
<style lang="less" scoped>
ul {
max-height: 162px;
max-height: 142px;
overflow-y: auto;
margin-top: 2px;
margin-bottom: 6px;
......@@ -63,6 +63,7 @@ ul {
// scrollbar-track-color: transparent;
// -ms-scrollbar-track-color: transparent;
&::-webkit-scrollbar {
display: none;
width: 2px;
height: 2px;
}
......
<template>
<div class="tips">
<div class="name">{{ name }}</div>
<div class="doc" v-if="doc">Markdown: {{ doc }}</div>
</div>
</template>
<script>
export default {
props: {
name: {
type: String,
default: ""
},
doc: {
type: String,
default: ""
}
},
data() {
return {};
}
};
</script>
<style lang="less" scoped>
.tips {
text-align: center;
.doc {
color: #666;
}
}
</style>
<template>
<div
v-if="isMobile"
@click="handleTool(info.name, info.startStr, info.endStr)"
class="tool_button"
>
<div v-if="isMobile" @click="mobileClick" class="tool_button">
<span :class="['icon iconfont', `icon-${info.icon}`]"></span>
</div>
<div
......@@ -33,9 +29,10 @@
</div>
</template>
<script>
import { formatText, checkBoswer } from "@/assets/js/utils";
import { checkBoswer } from "@/assets/js/utils";
import codeSelect from "./code-select";
import tableSelect from "./table-select";
import markdownDoc from "./markdown-doc";
export default {
components: { codeSelect, tableSelect },
props: {
......@@ -81,7 +78,11 @@ export default {
},
options() {
return {
content: this.info.tip,
customComponent: markdownDoc,
customProps: {
name: this.info.tip,
doc: this.info.doc
},
zIndex: parseInt(this.zIndex) + 1,
theme: this.darkMode ? "dark" : "light"
};
......@@ -110,7 +111,6 @@ export default {
customComponent: tableSelect,
customListeners: {
select: val => {
console.log(val);
this.handleTool("table", val, "");
this.closeTips();
}
......@@ -121,10 +121,16 @@ export default {
}
},
methods: {
mobileClick() {
setTimeout(() => {
this.handleTool(this.info.name, this.info.startStr, this.info.endStr);
}, 0);
},
closeTips() {
Array.from(document.getElementsByClassName("v-tip-container")).map(
item => {
item.remove();
// item.remove();
item.style.display = "none";
}
);
},
......@@ -161,6 +167,9 @@ export default {
case "cancelFullScreen":
this.$emit("setFullScreen", false);
break;
case "help":
this.$emit("updateShowHelp", true);
break;
default:
break;
}
......@@ -170,7 +179,7 @@ export default {
</script>
<style lang="less" scoped>
.tool_button {
padding: 4px 8px;
padding: 0 8px 8px;
box-sizing: border-box;
cursor: pointer;
&.active {
......@@ -181,6 +190,11 @@ export default {
.icon {
font-size: 18px;
color: var(--md-editor-text-color);
display: inline-block;
vertical-align: text-bottom;
@media screen and (max-width: 768px) {
vertical-align: text-top;
}
@media (any-hover: hover) {
&:hover {
color: var(--md-editor-border-color-active);
......@@ -191,6 +205,19 @@ export default {
font-size: 24px;
margin: 0 -4px;
}
&.icon-unorderedList,
&.icon-youxuliebiao {
font-size: 18px;
}
&.icon-geshishua {
font-size: 15px;
}
&.icon-lianjie {
font-size: 16px;
}
&.icon-help {
font-size: 19px;
}
}
}
</style>
......@@ -5,14 +5,16 @@
:class="['tab_item', { active: canPreview && !showPreview }]"
@click="setShowPreview(false)"
>
编辑
<span :class="['icon iconfont', `icon-bianji`]"></span>
<span v-if="!isMobile">编辑</span>
</div>
<div
v-if="canPreview"
:class="['tab_item', { active: showPreview }]"
@click="setShowPreview(true)"
>
预览
<span :class="['icon iconfont', `icon-yulan`]"></span>
<span v-if="!isMobile">预览</span>
</div>
</div>
<div class="header_tools" v-if="!showPreview">
......@@ -25,6 +27,7 @@
@updateText="handleUpdateText"
@upload="$emit('upload')"
@setFormatType="setFormatType"
@updateShowHelp="$emit('updateShowHelp', $event)"
:class="{ active: item.name === 'format' && formatType }"
v-for="(item, index) in toolsShow"
:key="index"
......@@ -43,7 +46,8 @@ import {
formatText,
getPosition,
removeBlankLine,
copyFormatRules
copyFormatRules,
checkBoswer
} from "@/assets/js/utils";
import toolButton from "./components/tool-button";
export default {
......@@ -102,6 +106,10 @@ export default {
return toolsList.filter(item => {
return isNotFalse(toolsOptions[item.name]);
});
},
isMobile() {
const isMobile = checkBoswer();
return isMobile;
}
},
watch: {
......@@ -126,6 +134,11 @@ export default {
return;
this.copyFormat();
}
},
formatType: {
handler: function(val) {
this.$emit("getFormatType", val);
}
}
},
data() {
......@@ -145,15 +158,11 @@ export default {
tip: "全屏模式"
},
toolButtonList: [
{
name: "format",
icon: "geshishua",
tip: "格式刷"
},
{
name: "bold",
icon: "bold",
tip: "粗体",
doc: "**内容**",
startStr: "**",
endStr: "**"
},
......@@ -161,6 +170,7 @@ export default {
name: "italic",
icon: "italic",
tip: "斜体",
doc: "_内容_",
startStr: "_",
endStr: "_"
},
......@@ -168,9 +178,15 @@ export default {
name: "quote",
icon: "yinyong",
tip: "插入引用",
doc: "> 空格",
startStr: "\n> ",
endStr: ""
},
{
name: "format",
icon: "geshishua",
tip: "格式刷"
},
{
name: "code",
icon: "code",
......@@ -182,13 +198,15 @@ export default {
name: "link",
icon: "lianjie",
tip: "添加链接",
startStr: "[链接](",
doc: "[标题](链接)",
startStr: "[链接标题](",
endStr: ")"
},
{
name: "ul",
icon: "unorderedList",
tip: "添加无序列表",
doc: "- 空格",
startStr: "\n- ",
endStr: ""
},
......@@ -196,13 +214,14 @@ export default {
name: "ol",
icon: "youxuliebiao",
tip: "添加有序列表",
doc: "1. 空格",
startStr: "",
endStr: ""
},
{
name: "file",
icon: "tupian",
tip: "上传文件",
tip: "上传图片",
startStr: "",
endStr: ""
},
......@@ -210,6 +229,7 @@ export default {
name: "task",
icon: "renwu",
tip: "添加任务列表",
doc: "- [空格]",
startStr: "\n- [ ] ",
endStr: ""
},
......@@ -221,6 +241,11 @@ export default {
"\n\n| 表头 | 表头 |\n| ------ | ------ |\n| 单元格 | 单元格 |\n| 单元格 | 单元格 |\n\n",
endStr: ""
},
{
name: "help",
icon: "help",
tip: "帮助"
},
{
name: "fullScreen",
icon: "fullScreen",
......@@ -255,7 +280,7 @@ export default {
!formatType
)
return;
this.handleUpdateText(formatType);
this.handleUpdateText({ ...formatType, copy: true });
if (this.lock) return;
this.formatType = "";
},
......@@ -282,10 +307,23 @@ export default {
this.$emit("update:showPreview", val);
},
handleUpdateText({ startStr, endStr }) {
handleUpdateText({ startStr, endStr, type, copy }) {
const originalText = this.text;
const selectionInfo = this.selectionInfo;
const newText = formatText(originalText, selectionInfo, startStr, endStr);
let newText = formatText(originalText, selectionInfo, startStr, endStr);
const s = selectionInfo.selectionStart;
const e = selectionInfo.selectionEnd;
if (copy) {
const handleBlank = newText
.slice(s, e)
.replace(/(\n{2,})/g, `${endStr}$1${startStr}`);
if (type !== "code") {
newText =
newText.slice(0, s) +
handleBlank +
newText.slice(e, newText.length);
}
}
const len =
selectionInfo.selectionEnd -
selectionInfo.selectionStart +
......@@ -303,11 +341,13 @@ export default {
selectionStart: "",
selectionEnd: ""
});
setTimeout(() => {
this.$nextTick(() => {
// setTimeout(() => {
textEl.focus();
textEl.setSelectionRange(cursorPoint + len, cursorPoint + len);
textEl.scrollTop = scrollTop;
}, 0);
});
// }, 0);
}
}
};
......@@ -320,6 +360,7 @@ export default {
height: 32px;
transition: border-bottom 0.3s;
border-bottom: 1px solid var(--md-editor-border-color);
// overflow-y: hidden;
&.active {
border-bottom: 1px solid var(--md-editor-border-color-active);
}
......@@ -327,25 +368,29 @@ export default {
display: flex;
justify-content: space-between;
font-size: 14px;
padding-bottom: 10px;
// padding-bottom: 10px;
box-sizing: border-box;
.tab_item {
color: var(--md-editor-text-color);
cursor: pointer;
position: relative;
padding: 0 6px;
// height: 28px;
padding: 0 6px 8px;
box-sizing: border-box;
&::after {
display: block;
content: "";
position: absolute;
bottom: -12px;
bottom: -2px;
width: 0;
height: 3px;
height: 2px;
left: 50%;
transform: translateX(-50%);
background: transparent;
transition: all 0.3s;
// @media screen and (max-width: 768px) {
// bottom: -2px;
// }
}
&:hover {
......@@ -366,13 +411,17 @@ export default {
& + .tab_item {
margin-left: 10px;
}
.iconfont {
font-size: 14px;
display: inline-block;
}
}
}
.header_tools {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 10px;
// padding-bottom: 10px;
box-sizing: border-box;
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册