import { createVNode as _createVNode } from "vue";
import "./styles/code.css";
import { computed, onMounted, ref, watch } from "vue";
import { flattenFragments } from "@veno-ui/utils";
import { defineComponent } from "../../utils";
import { makeThemeProps, provideTheme } from "../../composables/theme";
import { makeShapeProps, useShape } from "../../composables/shape";
import { useHighlighter } from "../../composables/highlighter";
import { useBackgroundColor } from "../../composables/color";
import { makeScrollbar, useScrollbar } from "../../composables/scrollbar";
const HTML_ESCAPE_TEST_RE = /[&<>"]/;
const HTML_ESCAPE_REPLACE_RE = /[&<>"]/g;
const HTML_REPLACEMENTS = {
  "&": "&amp;",
  "<": "&lt;",
  ">": "&gt;",
  '"': "&quot;"
};
function replaceUnsafeChar(ch) {
  return HTML_REPLACEMENTS[ch];
}
function escapeHtml(str) {
  if (HTML_ESCAPE_TEST_RE.test(str)) {
    return str.replace(HTML_ESCAPE_REPLACE_RE, replaceUnsafeChar);
  }
  return str;
}
const Code = defineComponent({
  name: "VeCode",
  props: {
    /**
     * @zh 需要高亮的代码
     */
    code: [String, Object],
    /**
     * @zh 背景颜色
     */
    color: String,
    /**
     * @zh 显示代码语言
     */
    showLanguage: Boolean,
    /**
     * @zh 显示行号
     */
    showLineNumbers: Boolean,
    /**
     * @zh 高亮的行号
     */
    highlightedLineNumbers: Array,
    /**
     * @zh 使用行内样式
     */
    inline: Boolean,
    /**
     * @zh 代码语言
     */
    language: {
      type: String,
      default: "text"
    },
    ...makeThemeProps(),
    ...makeShapeProps(),
    ...makeScrollbar()
  },
  setup(props, {
    slots
  }) {
    const {
      themeClasses
    } = provideTheme(props);
    const {
      shapeClasses
    } = useShape(props);
    const highlighter = useHighlighter();
    const {
      scrollbarClasses
    } = useScrollbar(props);
    const code = computed(() => {
      let value = "";
      if (props.code) {
        value = typeof props.code === "object" ? JSON.stringify(props.code, null, 2) : props.code ?? "";
      } else if (slots.default) {
        value = flattenFragments(slots.default()).filter((node) => node.children && typeof node.children === "string")[0]?.children;
      }
      return decodeURIComponent(value).replace(/\n$/, "").replace(/^\n/, "");
    });
    const highlightedCode = ref(escapeHtml(code.value));
    const {
      backgroundColorClasses,
      backgroundColorStyles
    } = useBackgroundColor(props, "color");
    const language = computed(() => typeof props.code === "object" ? "json" : props.language);
    const lineNumbers = computed(() => code.value.split("\n").map((v, i) => i + 1));
    const highlightedLines = computed(() => {
      return lineNumbers.value.filter((lineNumber) => {
        return props.highlightedLineNumbers?.some((v) => {
          let start = v;
          let end;
          if (typeof v === "object") {
            [start, end] = v;
          }
          if (start && end) {
            return lineNumber >= start && lineNumber <= end;
          }
          return lineNumber === start;
        });
      });
    });
    async function highlight() {
      highlightedCode.value = await highlighter.value?.highlight(code.value, language.value);
    }
    onMounted(highlight);
    watch([code, language], highlight);
    return () => {
      if (props.inline) {
        return _createVNode("code", {
          "class": ["ve-code", "ve-code--inline", themeClasses.value, shapeClasses.value, backgroundColorClasses.value],
          "style": backgroundColorStyles.value,
          "innerHTML": escapeHtml(highlightedCode.value)
        }, null);
      }
      const showLines = props.showLineNumbers || !!props.highlightedLineNumbers?.length;
      return _createVNode("div", {
        "class": ["ve-code", "ve-code--block", {
          "ve-code--show-line-numbers": !!props.showLineNumbers
        }, themeClasses.value, shapeClasses.value, backgroundColorClasses.value],
        "style": backgroundColorStyles.value
      }, [showLines && _createVNode("div", {
        "class": "ve-code__lines"
      }, [lineNumbers.value.map((number) => _createVNode("div", {
        "class": "ve-code__line"
      }, [highlightedLines.value.includes(number) && _createVNode("div", {
        "class": "ve-code__line-overlay",
        "innerHTML": "&nbsp;"
      }, null), props.showLineNumbers ? _createVNode("span", {
        "class": "ve-code__line-number"
      }, [number]) : _createVNode("br", null, null)]))]), _createVNode("pre", {
        "class": ["ve-code__preformatted", scrollbarClasses.value]
      }, [_createVNode("code", {
        "innerHTML": highlightedCode.value
      }, null)]), props.showLanguage && _createVNode("span", {
        "class": "ve-code__language"
      }, [language.value])]);
    };
  }
});
export {
  Code
};
//# sourceMappingURL=code.mjs.map
