{"version":3,"file":"JPreview.vue2.cjs","sources":["../../../../src/components/atoms/JPreview.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, onMounted, onUnmounted } from 'vue'\nimport { MdPreview } from 'md-editor-v3'\nimport 'md-editor-v3/lib/style.css'\nimport DOMPurify from 'dompurify'\n\nconst props = withDefaults(\n  defineProps<{\n    /** 마크다운 또는 HTML 내용 */\n    modelValue?: string\n    /** 테마 (light/dark) - 설정하지 않으면 자동으로 다크모드 감지 */\n    theme?: 'light' | 'dark'\n    /** 추가 CSS 클래스 */\n    class?: string\n  }>(),\n  {\n    modelValue: '',\n  },\n)\n\n// 다크모드 상태\nconst isDarkMode = ref(false)\n\n// 다크모드 감지 함수\nconst detectDarkMode = () => {\n  isDarkMode.value = document.documentElement.classList.contains('dark')\n}\n\n// 현재 테마 계산 (props.theme이 있으면 그것 사용, 없으면 자동 감지)\nconst currentTheme = computed(() => {\n  if (props.theme) {\n    return props.theme\n  }\n  return isDarkMode.value ? 'dark' : 'light'\n})\n\n// MutationObserver로 다크모드 변경 감지\nlet darkModeObserver: MutationObserver | null = null\n\nonMounted(() => {\n  // 초기 다크모드 상태 감지\n  detectDarkMode()\n  \n  // MutationObserver로 class 변경 감지\n  darkModeObserver = new MutationObserver(() => {\n    detectDarkMode()\n  })\n  \n  darkModeObserver.observe(document.documentElement, {\n    attributes: true,\n    attributeFilter: ['class'],\n  })\n})\n\nonUnmounted(() => {\n  if (darkModeObserver) {\n    darkModeObserver.disconnect()\n  }\n})\n\r\n/**\r\n * 콘텐츠 타입 자동 감지\r\n */\r\nfunction detectContentType(content: string): 'markdown' | 'html' {\r\n  const trimmed = content.trim()\r\n  \r\n  // HTML 문서 시작 태그 확인\r\n  if (\r\n    trimmed.startsWith('<!DOCTYPE html') ||\r\n    trimmed.startsWith('<!doctype html') ||\r\n    trimmed.startsWith('<!DOCTYPE HTML') ||\r\n    trimmed.startsWith('<!DOCTYPE Html') ||\r\n    trimmed.startsWith('<html') ||\r\n    trimmed.startsWith('<HTML') ||\r\n    trimmed.startsWith('<Html')\r\n  ) {\r\n    return 'html'\r\n  }\r\n  \r\n  return 'markdown'\r\n}\r\n\r\nconst contentType = computed(() => detectContentType(props.modelValue || ''))\r\n\r\nconst sanitizedHtml = computed(() => {\r\n  if (contentType.value === 'html') {\r\n    return DOMPurify.sanitize(props.modelValue || '', {\r\n      ALLOWED_TAGS: [\r\n        'p', 'br', 'strong', 'em', 'u', 's', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\r\n        'ul', 'ol', 'li', 'blockquote', 'pre', 'code', 'a', 'img', 'table', 'thead',\r\n        'tbody', 'tr', 'th', 'td', 'div', 'span', 'hr', 'blockquote', 'del', 'ins',\r\n        'sub', 'sup', 'kbd', 'mark', 'abbr', 'dfn', 'cite', 'q', 'samp', 'var',\r\n        'time', 'b', 'i', 'small', 'big', 'center', 'font', 'strike', 'tt',\r\n        'html', 'head', 'body', 'title', 'meta', 'link', 'style', 'script', 'noscript'\r\n      ],\r\n      ALLOWED_ATTR: [\r\n        'href', 'src', 'alt', 'title', 'width', 'height', 'class', 'id', 'style',\r\n        'target', 'rel', 'type', 'charset', 'name', 'content', 'http-equiv', 'lang'\r\n      ],\r\n      ALLOW_DATA_ATTR: false,\r\n    })\r\n  }\r\n  return ''\r\n})\r\n</script>\r\n\r\n<template>\n  <div :class=\"['j-preview-wrapper', props.class]\">\n    <!-- HTML 렌더링 -->\n    <div\n      v-if=\"contentType === 'html'\"\n      :class=\"['j-preview-html', currentTheme === 'dark' ? 'dark' : '']\"\n      v-html=\"sanitizedHtml\"\n    />\n    \n    <!-- 마크다운 렌더링 -->\n    <MdPreview\n      v-else\n      :model-value=\"modelValue\"\n      :theme=\"currentTheme\"\n      :preview-class-name=\"'j-preview-markdown'\"\n      language=\"en-US\"\n    />\n  </div>\n</template>\n\r\n<style scoped>\r\n.j-preview-wrapper {\r\n  @apply w-full;\r\n}\r\n\r\n.j-preview-html {\r\n  @apply prose prose-slate max-w-none;\r\n}\r\n\r\n.j-preview-html.dark {\r\n  @apply prose-invert;\r\n}\r\n\r\n:deep(.j-preview-markdown) {\r\n  @apply w-full;\r\n}\r\n</style>\r\n"],"names":["props","__props","isDarkMode","ref","detectDarkMode","currentTheme","computed","darkModeObserver","onMounted","onUnmounted","detectContentType","content","trimmed","contentType","sanitizedHtml","DOMPurify","_createElementBlock","_normalizeClass","_createBlock","_unref","MdPreview"],"mappings":"4aAMA,MAAMA,EAAQC,EAeRC,EAAaC,EAAAA,IAAI,EAAK,EAGtBC,EAAiB,IAAM,CAC3BF,EAAW,MAAQ,SAAS,gBAAgB,UAAU,SAAS,MAAM,CACvE,EAGMG,EAAeC,EAAAA,SAAS,IACxBN,EAAM,MACDA,EAAM,MAERE,EAAW,MAAQ,OAAS,OACpC,EAGD,IAAIK,EAA4C,KAEhDC,EAAAA,UAAU,IAAM,CAEdJ,EAAA,EAGAG,EAAmB,IAAI,iBAAiB,IAAM,CAC5CH,EAAA,CACF,CAAC,EAEDG,EAAiB,QAAQ,SAAS,gBAAiB,CACjD,WAAY,GACZ,gBAAiB,CAAC,OAAO,CAAA,CAC1B,CACH,CAAC,EAEDE,EAAAA,YAAY,IAAM,CACZF,GACFA,EAAiB,WAAA,CAErB,CAAC,EAKD,SAASG,EAAkBC,EAAsC,CAC/D,MAAMC,EAAUD,EAAQ,KAAA,EAGxB,OACEC,EAAQ,WAAW,gBAAgB,GACnCA,EAAQ,WAAW,gBAAgB,GACnCA,EAAQ,WAAW,gBAAgB,GACnCA,EAAQ,WAAW,gBAAgB,GACnCA,EAAQ,WAAW,OAAO,GAC1BA,EAAQ,WAAW,OAAO,GAC1BA,EAAQ,WAAW,OAAO,EAEnB,OAGF,UACT,CAEA,MAAMC,EAAcP,EAAAA,SAAS,IAAMI,EAAkBV,EAAM,YAAc,EAAE,CAAC,EAEtEc,EAAgBR,EAAAA,SAAS,IACzBO,EAAY,QAAU,OACjBE,EAAU,SAASf,EAAM,YAAc,GAAI,CAChD,aAAc,CACZ,IAAK,KAAM,SAAU,KAAM,IAAK,IAAK,KAAM,KAAM,KAAM,KAAM,KAAM,KACnE,KAAM,KAAM,KAAM,aAAc,MAAO,OAAQ,IAAK,MAAO,QAAS,QACpE,QAAS,KAAM,KAAM,KAAM,MAAO,OAAQ,KAAM,aAAc,MAAO,MACrE,MAAO,MAAO,MAAO,OAAQ,OAAQ,MAAO,OAAQ,IAAK,OAAQ,MACjE,OAAQ,IAAK,IAAK,QAAS,MAAO,SAAU,OAAQ,SAAU,KAC9D,OAAQ,OAAQ,OAAQ,QAAS,OAAQ,OAAQ,QAAS,SAAU,UAAA,EAEtE,aAAc,CACZ,OAAQ,MAAO,MAAO,QAAS,QAAS,SAAU,QAAS,KAAM,QACjE,SAAU,MAAO,OAAQ,UAAW,OAAQ,UAAW,aAAc,MAAA,EAEvE,gBAAiB,EAAA,CAClB,EAEI,EACR,8BAICgB,EAAAA,mBAgBM,MAAA,CAhBA,MAAKC,EAAAA,eAAA,CAAA,oBAAwBjB,EAAM,KAAK,CAAA,CAAA,GAGpCa,EAAA,QAAW,sBADnBG,EAAAA,mBAIE,MAAA,OAFC,yCAA0BX,EAAA,QAAY,OAAA,OAAA,EAAA,CAAA,EACvC,UAAQS,EAAA,KAAA,6BAIVI,EAAAA,YAMEC,QAAAC,EAAAA,SAAA,EAAA,OAJC,cAAanB,EAAA,WACb,MAAOI,EAAA,MACP,qBAAoB,qBACrB,SAAS,OAAA"}