게시물 HTML 블록 분리

This commit is contained in:
2026-06-26 15:23:19 +09:00
parent c77cf1032b
commit 8e3bf4a874
16 changed files with 233 additions and 101 deletions

View File

@@ -114,10 +114,18 @@ const panelTitle = computed(() => {
return '텍스트 색상'
}
if (props.panel.kind === 'embed') {
if (props.panel.kind === 'html') {
return 'HTML'
}
if (props.panel.kind === 'link') {
return '링크'
}
if (props.panel.kind === 'iframe') {
return 'iframe'
}
if (props.panel.kind === 'quote') {
return '인용'
}
@@ -154,8 +162,16 @@ const panelMeta = computed(() => {
return '선택한 텍스트'
}
if (props.panel.kind === 'embed') {
return 'URL·iframe'
if (props.panel.kind === 'html') {
return '사용자 HTML'
}
if (props.panel.kind === 'link') {
return 'URL 카드'
}
if (props.panel.kind === 'iframe') {
return 'sandbox iframe'
}
if (props.panel.kind === 'quote') {
@@ -252,17 +268,25 @@ const onPanelFocusOut = (event) => {
</div>
</template>
<template v-else-if="panel.kind === 'embed'">
<template v-else-if="['html', 'link', 'iframe'].includes(panel.kind)">
<label class="admin-editor-block-panel__field grid gap-2 text-sm">
<span class="font-semibold text-[#394047]">HTML 코드 또는 URL</span>
<span class="font-semibold text-[#394047]">
{{ panel.kind === 'link' ? 'URL' : panel.kind === 'iframe' ? 'iframe 코드' : 'HTML 코드' }}
</span>
<textarea
class="min-h-28 resize-y rounded border border-[#d7dde2] bg-[#eff1f2] px-3 py-2 font-mono text-xs leading-5 text-[#15171a] outline-none transition-colors focus:border-[#8e9cac]"
:value="panel.url"
placeholder="https://www.youtube.com/watch?v=... 또는 <iframe src=&quot;...&quot;></iframe>"
:placeholder="panel.kind === 'link' ? 'https://example.com' : panel.kind === 'iframe' ? '<iframe src=&quot;https://...&quot;></iframe>' : '<table>...</table>'"
@input="emit('update-embed-url', $event.target.value)"
/>
</label>
<p class="admin-editor-block-panel__hint mt-3 text-xs leading-relaxed text-[#8e9cac]">
<p v-if="panel.kind === 'html'" class="admin-editor-block-panel__hint mt-3 text-xs leading-relaxed text-[#8e9cac]">
본문 HTML은 그대로 표시하되 script, iframe, 이벤트 속성 같은 실행성 코드는 제거합니다. iframe은 /iframe 블록을 사용합니다.
</p>
<p v-else-if="panel.kind === 'link'" class="admin-editor-block-panel__hint mt-3 text-xs leading-relaxed text-[#8e9cac]">
YouTube·X(트위터)·Mastodon URL은 임베드로, 그 외 외부 URL은 링크 카드로 표시합니다.
</p>
<p v-else class="admin-editor-block-panel__hint mt-3 text-xs leading-relaxed text-[#8e9cac]">
YouTube·YouTube Shorts, X(트위터) 게시물 URL과 외부 서비스 iframe 코드를 지원합니다. iframe은 src 등 허용된 속성만 사용합니다.
</p>
</template>

View File

@@ -2800,14 +2800,14 @@ const appendImagesToActiveGallery = (images) => {
}
/**
* 현재 HTML 블록 값을 수정한다.
* @param {string} url - HTML 블록 값
* 현재 링크·iframe·HTML 블록 값을 수정한다.
* @param {string} url - 블록 값
* @returns {void}
*/
const updateActiveEmbedUrl = (url) => {
const block = activeBlockContext.value
if (!block || block.kind !== 'embed') {
if (!block || !['link', 'iframe', 'html'].includes(block.kind)) {
return
}
@@ -2819,12 +2819,7 @@ const updateActiveEmbedUrl = (url) => {
return
}
if (trimmed.includes('\n') || /^<iframe\b/i.test(trimmed)) {
replaceLineRange(block.startLine, block.endLine, [':::embed', trimmed, ':::'], false)
return
}
replaceLineRange(block.startLine, block.endLine, [trimmed], false)
replaceLineRange(block.startLine, block.endLine, [`:::${block.kind}`, trimmed, ':::'], false)
}
/**

View File

@@ -123,8 +123,8 @@ const props = defineProps({
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.8 2H3.2C1.985 2 1 2.895 1 4v16c0 1.105.985 2 2.2 2h17.6c1.215 0 2.2-.895 2.2-2V4c0-1.105-.985-2-2.2-2Z"></path><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16.5 11 12 15l-4.5-4"></path>
</template>
<!-- embed -->
<template v-else-if="commandId === 'embed'">
<!-- embed/html/link/iframe -->
<template v-else-if="['html', 'link', 'iframe'].includes(commandId)">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1" d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm.5 16c0 .3-.2.5-.5.5H5c-.3 0-.5-.2-.5-.5V9.8l4.7-5.3H19c.3 0 .5.2.5.5v14zm-6-9.5L16 12l-2.5 2.8 1.1 1L18 12l-3.5-3.5-1 1zm-3 0l-1-1L6 12l3.5 3.8 1.1-1L8 12l2.5-2.5z"></path>
</template>