운영 시작 버전 v1.0.0 정리

This commit is contained in:
2026-05-14 10:49:25 +09:00
parent 069d1bfbd4
commit 3b331b8fe6
18 changed files with 1679 additions and 94 deletions

View File

@@ -32,9 +32,54 @@ const createBlock = (type = 'paragraph', text = '', level = null, id = '', optio
ordered: options.ordered || false,
width: options.width || 'regular',
images: options.images || [],
meta: options.meta && typeof options.meta === 'object' ? { ...options.meta } : {}
meta: options.meta && typeof options.meta === 'object' ? { ...options.meta } : {},
calloutEmojiEnabled: options.calloutEmojiEnabled ?? true,
calloutEmoji: options.calloutEmoji || '💡',
calloutBackground: options.calloutBackground || 'blue'
})
const calloutBackgroundOptions = ['gray', 'blue', 'green', 'yellow', 'red', 'purple', 'pink']
/**
* 콜아웃 선언부 옵션을 파싱
* @param {string} line - 콜아웃 선언 라인
* @returns {{calloutEmojiEnabled: boolean, calloutEmoji: string, calloutBackground: string}} 콜아웃 옵션
*/
const parseCalloutOptions = (line) => {
const options = {
calloutEmojiEnabled: true,
calloutEmoji: '💡',
calloutBackground: 'blue'
}
const tokens = line.trim().split(/\s+/).slice(1)
tokens.forEach((token) => {
const [rawKey, ...rawValueParts] = token.split('=')
if (!rawKey || !rawValueParts.length) {
return
}
const key = rawKey.toLowerCase()
const value = rawValueParts.join('=').trim()
if (key === 'emoji') {
if (!value || value === 'none') {
options.calloutEmojiEnabled = false
options.calloutEmoji = '💡'
} else {
options.calloutEmojiEnabled = true
options.calloutEmoji = value
}
return
}
if (key === 'bg' && calloutBackgroundOptions.includes(value)) {
options.calloutBackground = value
}
})
return options
}
/**
* 이미지 마크다운 행을 이미지 데이터로 변환
* @param {string} line - 마크다운 행
@@ -240,9 +285,9 @@ const parseMarkdownBlocks = (markdown) => {
continue
}
if (trimmedLine === ':::callout') {
if (trimmedLine.startsWith(':::callout')) {
const { contentLines, nextIndex } = collectFencedLines(lines, index + 1)
blocks.push(createBlock('callout', contentLines.join('\n'), null, `block-${blocks.length}`))
blocks.push(createBlock('callout', contentLines.join('\n'), null, `block-${blocks.length}`, parseCalloutOptions(trimmedLine)))
index = nextIndex
continue
}
@@ -400,7 +445,12 @@ const showNextImage = () => {
<ProseImage v-else-if="block.type === 'image'" :src="block.url" :alt="block.alt" :variant="block.width">
{{ block.alt }}
</ProseImage>
<ProseCallout v-else-if="block.type === 'callout'">
<ProseCallout
v-else-if="block.type === 'callout'"
:emoji-enabled="block.calloutEmojiEnabled"
:emoji="block.calloutEmoji"
:background="block.calloutBackground"
>
{{ block.text }}
</ProseCallout>
<ProseToggle v-else-if="block.type === 'toggle'" :title="block.title || '더 보기'">

View File

@@ -1,7 +1,88 @@
<script setup>
const props = defineProps({
emojiEnabled: {
type: Boolean,
default: true
},
emoji: {
type: String,
default: '💡'
},
background: {
type: String,
default: 'blue'
}
})
const backgroundClass = computed(() => {
if (props.background === 'gray') {
return 'prose-callout--gray'
}
if (props.background === 'green') {
return 'prose-callout--green'
}
if (props.background === 'yellow') {
return 'prose-callout--yellow'
}
if (props.background === 'red') {
return 'prose-callout--red'
}
if (props.background === 'purple') {
return 'prose-callout--purple'
}
if (props.background === 'pink') {
return 'prose-callout--pink'
}
return 'prose-callout--blue'
})
</script>
<template>
<aside class="prose-callout prose-callout-card my-8 rounded-[10px] border border-[var(--site-line)] border-l-[3px] border-l-[var(--site-accent)] bg-[var(--site-panel)] p-5 pl-4 text-[15px] leading-8 text-[var(--site-text)]">
<div class="whitespace-pre-line">
<slot />
<aside
class="prose-callout prose-callout-card mt-8 rounded-[10px] p-5 text-[15px] leading-8 text-[var(--site-text)]"
:class="backgroundClass"
>
<div class="flex items-center gap-2">
<span v-if="emojiEnabled" class="inline-flex shrink-0 text-[20px] leading-none">{{ emoji || '💡' }}</span>
<div class="min-w-0 flex-1 whitespace-pre-line">
<slot />
</div>
</div>
</aside>
</template>
<style scoped>
.prose-callout--gray {
background: rgba(100, 116, 139, 0.12);
}
.prose-callout--blue {
background: rgba(59, 130, 246, 0.14);
}
.prose-callout--green {
background: rgba(34, 197, 94, 0.14);
}
.prose-callout--yellow {
background: rgba(245, 158, 11, 0.16);
}
.prose-callout--red {
background: rgba(239, 68, 68, 0.14);
}
.prose-callout--purple {
background: rgba(168, 85, 247, 0.14);
}
.prose-callout--pink {
background: rgba(236, 72, 153, 0.14);
}
</style>