forked from didirus/AstralRinth
Merge branch 'master' into redesign/new-promo-style
This commit is contained in:
@@ -14,7 +14,8 @@
|
||||
},
|
||||
{
|
||||
'id': 'report',
|
||||
'action': () => {}
|
||||
'link': 'https://example.com/report',
|
||||
'external': true,
|
||||
},
|
||||
{
|
||||
'id': 'remain',
|
||||
@@ -65,7 +66,8 @@
|
||||
},
|
||||
{
|
||||
'id': 'report',
|
||||
'action': () => {}
|
||||
'link': 'https://example.com/report',
|
||||
'external': true,
|
||||
},
|
||||
{
|
||||
'id': 'remain',
|
||||
|
||||
@@ -447,11 +447,10 @@ a,
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
:deep(.external-icon) {
|
||||
.external-icon {
|
||||
width: 0.75rem;
|
||||
height: 0.75rem;
|
||||
margin-bottom: auto;
|
||||
margin-left: 0.25rem;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ const accentedButton = computed(() =>
|
||||
|
||||
<template>
|
||||
<router-link
|
||||
v-if="link"
|
||||
v-if="link && link.startsWith('/')"
|
||||
class="btn"
|
||||
:class="{
|
||||
'icon-only': iconOnly,
|
||||
@@ -81,6 +81,35 @@ const accentedButton = computed(() =>
|
||||
<ExternalIcon v-if="external && !iconOnly" class="external-icon" />
|
||||
<UnknownIcon v-if="!$slots.default" />
|
||||
</router-link>
|
||||
<a
|
||||
v-else-if="link"
|
||||
class="btn"
|
||||
:class="{
|
||||
'icon-only': iconOnly,
|
||||
'btn-large': large,
|
||||
'btn-danger': color === 'danger',
|
||||
'btn-primary': color === 'primary',
|
||||
'btn-secondary': color === 'secondary',
|
||||
'btn-highlight': color === 'highlight',
|
||||
'btn-red': color === 'red',
|
||||
'btn-orange': color === 'orange',
|
||||
'btn-green': color === 'green',
|
||||
'btn-blue': color === 'blue',
|
||||
'btn-purple': color === 'purple',
|
||||
'btn-gray': color === 'gray',
|
||||
'btn-transparent': transparent,
|
||||
'btn-hover-filled': hoverFilled,
|
||||
'btn-hover-filled-only': hoverFilledOnly,
|
||||
'btn-outline': outline,
|
||||
'color-accent-contrast': accentedButton,
|
||||
}"
|
||||
:href="link"
|
||||
:target="external ? '_blank' : '_self'"
|
||||
>
|
||||
<slot />
|
||||
<ExternalIcon v-if="external && !iconOnly" class="external-icon" />
|
||||
<UnknownIcon v-if="!$slots.default" />
|
||||
</a>
|
||||
<button
|
||||
v-else
|
||||
class="btn"
|
||||
|
||||
@@ -135,7 +135,7 @@
|
||||
<Button :action="() => imageModal?.hide()"><XIcon /> Cancel</Button>
|
||||
<Button
|
||||
color="primary"
|
||||
:disabled="linkValidationErrorMessage || !linkUrl"
|
||||
:disabled="!canInsertImage"
|
||||
:action="
|
||||
() => {
|
||||
if (editor) markdownCommands.replaceSelection(editor, imageMarkdown)
|
||||
@@ -607,6 +607,14 @@ const handleImageUpload = async (files: FileList) => {
|
||||
const imageUploadOption = ref<string>('upload')
|
||||
const imageMarkdown = computed(() => (linkMarkdown.value.length ? `!${linkMarkdown.value}` : ''))
|
||||
|
||||
const canInsertImage = computed(() => {
|
||||
// Make sure the image url is valid, there is an image url, and there is alt text
|
||||
// They need to be valid, and not empty
|
||||
return (
|
||||
!linkValidationErrorMessage.value && linkUrl.value?.length > 0 && linkText.value?.length > 0
|
||||
)
|
||||
})
|
||||
|
||||
const youtubeRegex =
|
||||
/^(?:https?:)?(?:\/\/)?(?:youtu\.be\/|(?:www\.|m\.)?youtube\.com\/(?:watch|v|embed)(?:\.php)?(?:\?.*v=|\/))([a-zA-Z0-9_-]{7,15})(?:[?&][a-zA-Z0-9_-]+=[a-zA-Z0-9_-]+)*$/
|
||||
|
||||
@@ -623,22 +631,25 @@ const linkModal = ref<InstanceType<typeof Modal> | null>(null)
|
||||
const imageModal = ref<InstanceType<typeof Modal> | null>(null)
|
||||
const videoModal = ref<InstanceType<typeof Modal> | null>(null)
|
||||
|
||||
function resetModalStates() {
|
||||
linkText.value = ''
|
||||
linkUrl.value = ''
|
||||
linkValidationErrorMessage.value = undefined
|
||||
}
|
||||
|
||||
function openLinkModal() {
|
||||
if (editor) linkText.value = markdownCommands.yankSelection(editor)
|
||||
linkUrl.value = ''
|
||||
resetModalStates()
|
||||
linkModal.value?.show()
|
||||
}
|
||||
|
||||
function openImageModal() {
|
||||
linkValidationErrorMessage.value = undefined
|
||||
linkText.value = ''
|
||||
linkUrl.value = ''
|
||||
resetModalStates()
|
||||
imageModal.value?.show()
|
||||
}
|
||||
|
||||
function openVideoModal() {
|
||||
linkText.value = ''
|
||||
linkUrl.value = ''
|
||||
resetModalStates()
|
||||
videoModal.value?.show()
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -18,9 +18,20 @@
|
||||
:hover-filled-only="option.hoverFilledOnly"
|
||||
transparent
|
||||
:action="
|
||||
option.action
|
||||
? () => {
|
||||
option.action()
|
||||
if (!option.remainOnClick) {
|
||||
close()
|
||||
}
|
||||
}
|
||||
: null
|
||||
"
|
||||
:link="option.link ? option.link : null"
|
||||
:external="option.external ? option.external : false"
|
||||
@click="
|
||||
() => {
|
||||
option.action()
|
||||
if (!option.remainOnClick) {
|
||||
if (option.link && !option.remainOnClick) {
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,9 @@ const toggleCodeBlock: Command = ({ state, dispatch }) => {
|
||||
}
|
||||
|
||||
const toggleSpoiler: Command = ({ state, dispatch }) => {
|
||||
return toggleAround(state, dispatch, '||', '||')
|
||||
// Insert details tag with a summary tag at the start
|
||||
const detailsTags = ['\n<details>\n<summary>Spoiler</summary>\n\n', '\n\n</details>\n\n']
|
||||
return toggleAround(state, dispatch, detailsTags[0], detailsTags[1])
|
||||
}
|
||||
|
||||
const toggleHeader: Command = ({ state, dispatch }) => {
|
||||
|
||||
Reference in New Issue
Block a user