Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
weixin_43676597
Awesome-Markdown-Editor
提交
89f3b395
Awesome-Markdown-Editor
项目概览
weixin_43676597
/
Awesome-Markdown-Editor
与 Fork 源项目一致
Fork自
gitcode_dev / Awesome-Markdown-Editor
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Awesome-Markdown-Editor
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
89f3b395
编写于
7月 27, 2021
作者:
璃白.
🌻
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat:添加@事件
上级
549b7a90
变更
9
展开全部
隐藏空白更改
内联
并排
Showing
9 changed file
with
355 addition
and
75 deletion
+355
-75
dist/index.html
dist/index.html
+47
-2
dist/markdown-editor.js
dist/markdown-editor.js
+1
-1
src/App.vue
src/App.vue
+12
-7
src/components/content/components/help-doc.vue
src/components/content/components/help-doc.vue
+1
-0
src/components/content/components/select-user.vue
src/components/content/components/select-user.vue
+0
-54
src/components/content/components/user-select.vue
src/components/content/components/user-select.vue
+157
-0
src/components/content/md-textarea.vue
src/components/content/md-textarea.vue
+83
-9
src/components/header/components/code-select.vue
src/components/header/components/code-select.vue
+1
-2
src/main.js
src/main.js
+53
-0
未找到文件。
dist/index.html
浏览文件 @
89f3b395
...
...
@@ -9,7 +9,7 @@
.md_container
{
/* width: 600px !important; */
margin
:
40px
auto
;
margin-top
:
600px
;
/* margin-top: 600px; */
}
body
{
/* background-color: #222226; */
...
...
@@ -86,6 +86,7 @@ void main()
"
## edswgdfgdfgdfg
\n
**dfgdfgdfg**
\n
_ergdfgdfg_
\n
> ergergdfg
\n
```
\n
wefgdfsfdgdf
\n
```
\n
- efwefsdfsdf
\n\n\n
sdgfdfgdfgdfg
\n\n\n
edrfgdfgdfg
\n\n\n\n
ergergergergerg
\n
ergergergerg
\n\n\n
edrfgdfgdfg
\n\n\n\n
ergergergergerg
\n
ergergergerg
\n\n\n
edrfgdfgdfg
\n\n\n\n
ergergergergerg
\n
ergergergerg
"
,
value
:
"
![img](https://img2.baidu.com/it/u=4025475678,645544065&fm=26&fmt=auto&gp=0.jpg)
"
,
value
:
""
,
disabled
:
false
,
themeOptions
:
{
dark
:
false
,
...
...
@@ -166,7 +167,51 @@ void main()
setTimeout
(()
=>
{
callback
(
newLinks
);
},
2000
);
}
},
// queryUserList: function(val, callback) {
// const list = [
// {
// id: 1,
// name: "藤原拓海",
// avatar:
// "https://img2.baidu.com/it/u=2380211986,3979961921&fm=26&fmt=auto&gp=0.jpg"
// },
// {
// id: 2,
// name: "高桥凉介",
// avatar:
// "https://img0.baidu.com/it/u=777620324,2343967729&fm=26&fmt=auto&gp=0.jpg"
// },
// {
// id: 3,
// name: "马奎斯",
// avatar:
// "https://img2.baidu.com/it/u=1297316011,1869565258&fm=26&fmt=auto&gp=0.jpg"
// },
// {
// id: 4,
// name: "王一博",
// avatar:
// "https://img2.baidu.com/it/u=298051053,3773223854&fm=26&fmt=auto&gp=0.jpg"
// },
// {
// id: 5,
// name: "王俊凯",
// avatar:
// "https://img1.baidu.com/it/u=2378425879,2273515018&fm=26&fmt=auto&gp=0.jpg"
// }
// ];
// if (!val) {
// callback(list);
// return;
// }
// callback(
// list.filter(item => {
// return item.name.includes(val);
// })
// );
// }
});
// ee.focus();
...
...
dist/markdown-editor.js
浏览文件 @
89f3b395
此差异已折叠。
点击以展开。
src/App.vue
浏览文件 @
89f3b395
...
...
@@ -59,6 +59,7 @@
:disabled=
"disabled"
:show-help=
"showHelp"
:formatType=
"formatType"
:userList=
"userList"
:ref=
"'md_textarea' + id"
@
tab=
"$refs['md_header' + id].tab()"
@
submit=
"submit"
...
...
@@ -66,6 +67,7 @@
@
getFilteredTags=
"filteredTags = $event"
@
updateShowHelp=
"showHelp = $event"
@
renderLinksHtml=
"renderLinksHtml"
@
queryUserList=
"queryUserList"
v-else
/>
<div
v-if=
"maxLength && showWordLimit && !showPreview"
class=
"word_limit"
>
...
...
@@ -214,6 +216,7 @@ export default {
htmlMinHeight
:
150
,
showHelp
:
false
,
textLength
:
""
,
userList
:
[],
selectionInfo
:
{
selectorId
:
""
,
selectionStart
:
""
,
...
...
@@ -228,10 +231,6 @@ export default {
html
:
this
.
html
});
},
0
);
// if(this.isMobile) {
// }
},
watch
:
{
focus
:
{
...
...
@@ -276,16 +275,13 @@ export default {
html
:
{
immediate
:
false
,
handler
:
function
(
val
)
{
console
.
log
(
"
html update
"
);
const
emitContent
=
{
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
);
...
...
@@ -354,6 +350,15 @@ export default {
html
:
this
.
html
});
},
queryUserList
(
keyWord
)
{
const
_this
=
this
;
this
.
$emit
(
"
queryUserList
"
,
{
keyWord
,
callback
:
function
(
list
)
{
_this
.
userList
=
list
;
}
});
},
renderLinksHtml
({
vDom
,
links
})
{
new
Promise
((
resolve
,
reject
)
=>
{
this
.
$emit
(
"
renderLinks
"
,
{
...
...
src/components/content/components/help-doc.vue
浏览文件 @
89f3b395
...
...
@@ -157,6 +157,7 @@ export default {
padding-right: 14px;
height: 100%;
scrollbar-color: transparent transparent;
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
}
...
...
src/components/content/components/select-user.vue
已删除
100644 → 0
浏览文件 @
549b7a90
<
template
>
<div
class=
"md_select_user"
:style=
"
{ left: this.left + 'px', top: this.top + 'px' }"
>
选择用户弹窗
</div>
</
template
>
<
script
>
export
default
{
props
:
{
position
:
{
type
:
Object
,
default
:
()
=>
{
return
{
left
:
0
,
top
:
0
};
}
}
},
watch
:
{
position
:
{
immediate
:
true
,
handler
:
function
({
left
,
top
})
{
this
.
left
=
left
+
14
;
this
.
top
=
top
+
14
;
}
}
},
data
()
{
return
{
left
:
0
,
top
:
0
};
}
};
</
script
>
<
style
lang=
"less"
scoped
>
.md_select_user {
position: fixed;
width: 100px;
height: 200px;
background: #fff;
border: 1px solid red;
box-shadow: 0 1px 6px rgb(0 0 0 / 10%);
border: 1px solid var(--md-editor-border-color);
border-radius: 4px;
z-index: var(--md-editor-fullScrren-zIndex);
box-sizing: border-box;
padding: 6px 8px;
margin: 0;
}
</
style
>
src/components/content/components/user-select.vue
0 → 100644
浏览文件 @
89f3b395
<
template
>
<div
class=
"md_select_container"
:style=
"
{ left: this.left + 'px', top: this.top + 'px' }"
>
<ul
v-show=
"userList.length"
class=
"md_select_user"
>
<li
@
click=
"selectUser(item)"
v-for=
"(item, index) in userList"
:key=
"index"
>
<img
class=
"md_select_user_avatar"
:src=
"item.avatar"
/>
<div
class=
"md_select_user_info"
>
<div
class=
"md_select_user_name"
>
{{
item
.
name
}}
</div>
<div
class=
"md_select_user_desc"
>
最近回答过类似问题
</div>
</div>
</li>
</ul>
<div
v-show=
"userList.length"
class=
"after"
></div>
<div
v-show=
"!userList.length"
class=
"md_select_no_data"
>
轻敲空格完成输入
</div>
</div>
</
template
>
<
script
>
export
default
{
props
:
{
position
:
{
type
:
Object
,
default
:
()
=>
{
return
{
left
:
0
,
top
:
0
};
}
},
userList
:
{
type
:
Array
,
default
:
()
=>
[]
}
},
watch
:
{
position
:
{
immediate
:
true
,
handler
:
function
({
left
,
top
})
{
this
.
left
=
left
+
14
;
this
.
top
=
top
+
20
;
}
}
},
data
()
{
return
{
left
:
0
,
top
:
0
};
},
methods
:
{
selectUser
(
user
)
{
this
.
$emit
(
"
selectUser
"
,
user
);
}
}
};
</
script
>
<
style
lang=
"less"
scoped
>
.md_select_container {
position: relative;
position: fixed;
background: #fff;
box-shadow: 0 1px 6px rgb(0 0 0 / 10%);
border: 1px solid var(--md-editor-border-color);
border-radius: 4px;
z-index: var(--md-editor-fullScrren-zIndex);
margin: 0;
.after {
pointer-events: none;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 28px;
background: linear-gradient(
to top,
var(--md-editor-content-bg-color),
rgba(255, 255, 255, 0)
);
}
.md_select_user {
max-height: 214px;
width: 180px;
// background: #fff;
// box-shadow: 0 1px 6px rgb(0 0 0 / 10%);
// border: 1px solid var(--md-editor-border-color);
// border-radius: 4px;
// z-index: var(--md-editor-fullScrren-zIndex);
// margin: 0;
padding: 6px 0;
box-sizing: border-box;
overflow-y: auto;
scrollbar-color: transparent transparent;
scrollbar-width: none;
margin: 0 !important;
list-style: none !important;
&::-webkit-scrollbar {
display: none;
}
&::-webkit-scrollbar-thumb {
border-radius: 1em;
background-color: rgba(50, 50, 50, 0.3);
}
&::-webkit-scrollbar-track {
border-radius: 1em;
background-color: rgba(50, 50, 50, 0);
}
li {
display: flex;
box-sizing: border-box;
padding: 6px 8px;
cursor: pointer;
&:hover {
background: #f5f7fa;
}
// & + li {
// margin-top: 10px;
// }
.md_select_user_avatar {
width: 44px;
height: 44px;
border-radius: 50%;
object-fit: cover;
margin-right: 8px;
}
.md_select_user_info {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: flex-start;
.md_select_user_name {
font-size: 14px;
color: var(--md-editor-text-color-active);
}
.md_select_user_desc {
font-size: 12px;
color: var(--md-editor-helpdoc-color);
}
}
}
}
.md_select_no_data {
font-size: 12px;
padding: 4px 8px;
box-sizing: border-box;
color: var(--md-editor-helpdoc-color);
}
}
</
style
>
src/components/content/md-textarea.vue
浏览文件 @
89f3b395
...
...
@@ -8,11 +8,11 @@
@
focus=
"setFocus(true)"
@
blur=
"setFocus(false)"
@
paste=
"pasteFile"
@
keydown.enter=
"$emit('enter')"
@
keydown.stop.50=
"keyup"
@
keydown.enter=
"handleEnter"
@
keydown.meta.enter.exact=
"submit"
@
keydown.ctrl.enter.exact=
"submit"
@
keydown.tab.prevent=
"$emit('tab')"
@
keyup=
"keyup"
v-model=
"textContent"
:placeholder=
"placeholder"
:maxlength=
"maxLength"
...
...
@@ -37,7 +37,12 @@
/>
</transition>
<transition
name=
"slideup-fade"
>
<selectUser
v-show=
"showSelectUser"
:position=
"selectUserPosition"
/>
<selectUser
:userList=
"userList"
v-show=
"showSelectUser"
:position=
"selectUserPosition"
@
selectUser=
"selectUser"
/>
</transition>
</div>
</
template
>
...
...
@@ -52,7 +57,7 @@ import {
throttle
as
throttleFn
}
from
"
@/assets/js/utils
"
;
import
marked
from
"
marked
"
;
import
selectUser
from
"
./components/
select-user
"
;
import
selectUser
from
"
./components/
user-select
"
;
import
helpDoc
from
"
./components/help-doc
"
;
import
DOMPurify
from
"
dompurify
"
;
export
default
{
...
...
@@ -119,6 +124,10 @@ export default {
showHelp
:
{
type
:
Boolean
,
default
:
false
},
userList
:
{
type
:
Array
,
default
:
()
=>
[]
}
},
...
...
@@ -128,6 +137,11 @@ export default {
editorHeight
:
"
auto
"
,
editorOverFlow
:
"
auto
"
,
showSelectUser
:
false
,
queryInfo
:
{
startPosition
:
""
,
endPosition
:
""
,
keyWord
:
""
},
selectUserPosition
:
{
left
:
0
,
top
:
0
}
};
},
...
...
@@ -173,6 +187,13 @@ export default {
this
.
reSizeTextareaHeight
();
},
0
);
}
},
showSelectUser
:
{
handler
:
function
(
val
)
{
if
(
!
val
)
{
this
.
resetQueryInfo
();
}
}
}
},
beforeDestroy
()
{
...
...
@@ -198,6 +219,13 @@ export default {
this
.
$emit
(
"
update:htmlMinHeight
"
,
height
);
},
0
);
},
resetQueryInfo
()
{
this
.
queryInfo
=
{
startPosition
:
""
,
endPosition
:
""
,
keyWord
:
""
};
},
transferMarkdown
(
val
)
{
marked
.
setOptions
({
breaks
:
true
,
...
...
@@ -232,18 +260,48 @@ export default {
if
(
links
.
length
)
this
.
$emit
(
"
renderLinksHtml
"
,
{
vDom
,
links
});
},
input
()
{
if
(
this
.
showSelectUser
)
this
.
handleQueryUser
();
this
.
$emit
(
"
update:textLength
"
,
this
.
textContent
.
length
);
this
.
emitText
();
},
selectUser
(
user
)
{
const
originalText
=
this
.
textContent
;
const
queryInfo
=
this
.
queryInfo
;
const
cursorPosition
=
getPosition
(
this
.
id
);
const
username
=
user
.
name
+
"
"
;
const
newText
=
originalText
.
slice
(
0
,
queryInfo
.
startPosition
)
+
username
+
originalText
.
slice
(
queryInfo
.
endPosition
);
this
.
textContent
=
newText
;
this
.
emitText
();
this
.
showSelectUser
=
false
;
this
.
$nextTick
(()
=>
{
const
textEl
=
document
.
getElementById
(
this
.
id
);
textEl
.
setSelectionRange
(
cursorPosition
+
username
.
length
,
cursorPosition
+
username
.
length
);
textEl
.
focus
();
});
},
handleQueryUser
()
{
const
endPosition
=
getPosition
(
this
.
id
);
const
startPosition
=
this
.
queryInfo
.
startPosition
+
1
;
const
keyWord
=
this
.
textContent
.
slice
(
startPosition
,
endPosition
);
this
.
queryInfo
.
endPosition
=
endPosition
;
if
(
endPosition
<
startPosition
||
keyWord
.
slice
(
-
1
)
===
"
"
)
{
this
.
showSelectUser
=
false
;
return
;
}
this
.
queryInfo
.
keyWord
=
keyWord
;
this
.
$emit
(
"
queryUserList
"
,
keyWord
);
},
keyup
(
e
)
{
if
(
e
.
key
===
"
@
"
)
{
this
.
createSelectUserDialog
();
}
// console.log(e);
if
(
e
.
code
===
"
Space
"
||
e
.
code
===
"
Enter
"
)
{
this
.
showSelectUser
=
false
;
}
},
createSelectUserDialog
()
{
const
textEl
=
document
.
getElementById
(
this
.
id
);
...
...
@@ -283,6 +341,9 @@ export default {
};
textEl
.
parentNode
.
removeChild
(
hideEl
);
this
.
showSelectUser
=
true
;
this
.
queryInfo
.
startPosition
=
getPosition
(
this
.
id
);
this
.
queryInfo
.
endPosition
=
getPosition
(
this
.
id
);
this
.
$emit
(
"
queryUserList
"
,
this
.
queryInfo
.
keyWord
);
});
},
createHideEl
(
type
)
{
...
...
@@ -326,6 +387,18 @@ export default {
this
.
autoSize
&&
!
this
.
fullScreen
&&
!
this
.
height
?
"
hidden
"
:
"
auto
"
;
textEl
.
parentNode
.
removeChild
(
hideEl
);
},
handleEnter
()
{
if
(
this
.
showSelectUser
)
{
const
textEl
=
document
.
getElementById
(
this
.
id
);
textEl
.
blur
();
setTimeout
(()
=>
{
textEl
.
focus
();
// this.showSelectUser = false;
},
0
);
return
;
}
this
.
$emit
(
"
enter
"
);
},
submit
()
{
this
.
$emit
(
"
submit
"
);
},
...
...
@@ -398,6 +471,7 @@ export default {
height: var(--md-editor-height);
resize: none;
font-size: 14px;
line-height: 18px;
word-break: break-all;
font-family: "Menlo", -apple-system, SF UI Text, Arial, PingFang SC,
Hiragino Sans GB, Microsoft YaHei, WenQuanYi Micro Hei, sans-serif, SimHei,
...
...
src/components/header/components/code-select.vue
浏览文件 @
89f3b395
...
...
@@ -82,8 +82,7 @@ ul {
padding-top: 4px;
box-sizing: border-box;
scrollbar-color: transparent transparent;
// scrollbar-track-color: transparent;
// -ms-scrollbar-track-color: transparent;
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
...
...
src/main.js
浏览文件 @
89f3b395
...
...
@@ -23,6 +23,7 @@ function initMdEditor(obj) {
onInput
=
()
=>
{},
onSubmit
=
()
=>
{},
renderLinks
=
()
=>
{},
queryUserList
=
()
=>
{},
placeholder
,
value
,
disabled
,
...
...
@@ -113,6 +114,58 @@ function initMdEditor(obj) {
renderLinks
(
links
,
function
(
res
)
{
callback
(
res
);
});
},
queryUserList
({
keyWord
,
callback
})
{
// queryUserList(keyWord, function(res) {
const
list
=
[
{
id
:
1
,
name
:
"
藤原拓海
"
,
avatar
:
"
https://img2.baidu.com/it/u=2380211986,3979961921&fm=26&fmt=auto&gp=0.jpg
"
},
{
id
:
2
,
name
:
"
高桥凉介
"
,
avatar
:
"
https://img0.baidu.com/it/u=777620324,2343967729&fm=26&fmt=auto&gp=0.jpg
"
},
{
id
:
3
,
name
:
"
马奎斯
"
,
avatar
:
"
https://img2.baidu.com/it/u=1297316011,1869565258&fm=26&fmt=auto&gp=0.jpg
"
},
{
id
:
4
,
name
:
"
王一博
"
,
avatar
:
"
https://img2.baidu.com/it/u=298051053,3773223854&fm=26&fmt=auto&gp=0.jpg
"
},
{
id
:
5
,
name
:
"
王俊凯
"
,
avatar
:
"
https://img1.baidu.com/it/u=2378425879,2273515018&fm=26&fmt=auto&gp=0.jpg
"
},
{
id
:
6
,
name
:
"
易烊千玺
"
,
avatar
:
"
https://img0.baidu.com/it/u=2227200088,1939721201&fm=26&fmt=auto&gp=0.jpg
"
}
];
if
(
!
keyWord
)
{
callback
(
list
);
return
;
}
callback
(
list
.
filter
(
item
=>
{
return
item
.
name
.
includes
(
keyWord
);
})
);
// });
}
};
this
.
vEl
=
new
Vue
({
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录