콜아웃 제목과 기본 아이콘 정리
This commit is contained in:
@@ -30,18 +30,67 @@ export const CALLOUT_BACKGROUND_SWATCHES = QUOTE_BACKGROUND_SWATCHES
|
||||
/** @type {string[]} */
|
||||
export const CALLOUT_EMOJI_OPTIONS = ['💡', '⚠️', '❗', '✅', '📌', '🔥', '💬']
|
||||
|
||||
/**
|
||||
* 옵션 선언부를 key=value 토큰 목록으로 분리한다.
|
||||
* @param {string} input - 옵션 문자열
|
||||
* @returns {string[]} 토큰 목록
|
||||
*/
|
||||
const tokenizeOptionString = (input) => {
|
||||
const tokens = []
|
||||
const pattern = /[^\s"']+(?:"[^"]*"|'[^']*')?/g
|
||||
const matches = String(input ?? '').match(pattern)
|
||||
|
||||
return matches ? tokens.concat(matches) : tokens
|
||||
}
|
||||
|
||||
/**
|
||||
* 선언부 옵션 값을 정리한다.
|
||||
* @param {string} value - 원본 값
|
||||
* @returns {string} 정리된 값
|
||||
*/
|
||||
const normalizeOptionValue = (value) => {
|
||||
const normalized = String(value ?? '').trim()
|
||||
|
||||
if ((normalized.startsWith('"') && normalized.endsWith('"'))
|
||||
|| (normalized.startsWith("'") && normalized.endsWith("'"))) {
|
||||
return normalized.slice(1, -1)
|
||||
}
|
||||
|
||||
return normalized
|
||||
}
|
||||
|
||||
/**
|
||||
* 선언부 옵션 값을 직렬화한다.
|
||||
* @param {string} value - 옵션 값
|
||||
* @returns {string} 직렬화 값
|
||||
*/
|
||||
const serializeOptionValue = (value) => {
|
||||
const normalized = String(value ?? '').trim()
|
||||
|
||||
if (!normalized) {
|
||||
return ''
|
||||
}
|
||||
|
||||
if (/[\s"']/.test(normalized)) {
|
||||
return `"${normalized.replace(/"/g, '\\"')}"`
|
||||
}
|
||||
|
||||
return normalized
|
||||
}
|
||||
|
||||
/**
|
||||
* 콜아웃 선언부 옵션을 파싱한다.
|
||||
* @param {string} line - 콜아웃 선언 라인
|
||||
* @returns {{ calloutEmojiEnabled: boolean, calloutEmoji: string, calloutBackground: string }}
|
||||
* @returns {{ calloutEmojiEnabled: boolean, calloutEmoji: string, calloutBackground: string, title: string }}
|
||||
*/
|
||||
export const parseCalloutOptions = (line) => {
|
||||
const options = {
|
||||
calloutEmojiEnabled: true,
|
||||
calloutEmojiEnabled: false,
|
||||
calloutEmoji: '💡',
|
||||
calloutBackground: 'blue'
|
||||
calloutBackground: 'blue',
|
||||
title: ''
|
||||
}
|
||||
const tokens = String(line ?? '').trim().split(/\s+/).slice(1)
|
||||
const tokens = tokenizeOptionString(String(line ?? '').trim()).slice(1)
|
||||
|
||||
tokens.forEach((token) => {
|
||||
const [rawKey, ...rawValueParts] = token.split('=')
|
||||
@@ -51,7 +100,7 @@ export const parseCalloutOptions = (line) => {
|
||||
}
|
||||
|
||||
const key = rawKey.toLowerCase()
|
||||
const value = rawValueParts.join('=').trim()
|
||||
const value = normalizeOptionValue(rawValueParts.join('='))
|
||||
|
||||
if (key === 'emoji') {
|
||||
if (!value || value === 'none') {
|
||||
@@ -67,6 +116,11 @@ export const parseCalloutOptions = (line) => {
|
||||
|
||||
if (key === 'bg' && CALLOUT_BACKGROUND_OPTIONS.includes(value)) {
|
||||
options.calloutBackground = value
|
||||
return
|
||||
}
|
||||
|
||||
if (key === 'title') {
|
||||
options.title = value
|
||||
}
|
||||
})
|
||||
|
||||
@@ -75,15 +129,17 @@ export const parseCalloutOptions = (line) => {
|
||||
|
||||
/**
|
||||
* 콜아웃 선언 줄을 만든다.
|
||||
* @param {{ calloutEmojiEnabled?: boolean, calloutEmoji?: string, calloutBackground?: string }} options - 옵션
|
||||
* @param {{ calloutEmojiEnabled?: boolean, calloutEmoji?: string, calloutBackground?: string, title?: string }} options - 옵션
|
||||
* @returns {string} 선언 줄
|
||||
*/
|
||||
export const buildCalloutOpenerLine = (options = {}) => {
|
||||
const emojiEnabled = options.calloutEmojiEnabled !== false
|
||||
const emojiEnabled = options.calloutEmojiEnabled === true
|
||||
const emoji = emojiEnabled ? (options.calloutEmoji || '💡') : 'none'
|
||||
const background = CALLOUT_BACKGROUND_OPTIONS.includes(options.calloutBackground)
|
||||
? options.calloutBackground
|
||||
: 'blue'
|
||||
const title = serializeOptionValue(options.title)
|
||||
const titleOption = title ? ` title=${title}` : ''
|
||||
|
||||
return `:::callout emoji=${emoji} bg=${background}`
|
||||
return `:::callout emoji=${emoji} bg=${background}${titleOption}`
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { buildCalloutOpenerLine } from './markdown-callout.js'
|
||||
|
||||
const BLANK_PARAGRAPH_MARKER = '<!--sori:blank-paragraph-->'
|
||||
|
||||
const blockSpacingTypes = new Set(['list'])
|
||||
@@ -59,13 +61,20 @@ const serializeLegacyBlock = (block = {}, index = 0, total = 1) => {
|
||||
}
|
||||
|
||||
if (type === 'callout') {
|
||||
const emoji = block.calloutEmojiEnabled === false
|
||||
? 'none'
|
||||
: (block.calloutEmoji || '💡')
|
||||
const background = block.calloutBackground || 'blue'
|
||||
|
||||
return text
|
||||
? { type, value: `:::callout emoji=${emoji} bg=${background}\n${text}\n:::` }
|
||||
? {
|
||||
type,
|
||||
value: [
|
||||
buildCalloutOpenerLine({
|
||||
calloutEmojiEnabled: block.calloutEmojiEnabled,
|
||||
calloutEmoji: block.calloutEmoji,
|
||||
calloutBackground: block.calloutBackground,
|
||||
title: block.title
|
||||
}),
|
||||
text,
|
||||
':::'
|
||||
].join('\n')
|
||||
}
|
||||
: null
|
||||
}
|
||||
|
||||
|
||||
@@ -94,10 +94,10 @@ export const MARKDOWN_SLASH_COMMANDS = [
|
||||
{
|
||||
id: 'callout',
|
||||
label: '콜아웃',
|
||||
description: '강조 안내(첫 줄: :::callout emoji=💡 bg=blue)',
|
||||
description: '강조 안내(첫 줄: :::callout emoji=none bg=blue)',
|
||||
keywords: ['callout', 'notice', 'info', '콜아웃'],
|
||||
action: 'lines',
|
||||
lines: [':::callout emoji=💡 bg=blue', '', ':::']
|
||||
lines: [':::callout emoji=none bg=blue', '', ':::']
|
||||
},
|
||||
{
|
||||
id: 'toggle',
|
||||
|
||||
Reference in New Issue
Block a user