You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@answer.apache.org by ro...@apache.org on 2024/09/06 09:43:52 UTC

(incubator-answer-plugins) 01/06: feat: codehight frontend function

This is an automated email from the ASF dual-hosted git repository.

robin0716 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-answer-plugins.git

commit 0c29f4a99ce8f41b837f1bd49a5c8e4559360483
Author: Chen <22...@qq.com>
AuthorDate: Wed Sep 4 16:55:05 2024 +0800

    feat: codehight frontend function
---
 render-markdown-codehighlight/.eslintrc.cjs        |  18 +
 render-markdown-codehighlight/.prettierrc.json     |   8 +
 render-markdown-codehighlight/README.md            |   1 +
 render-markdown-codehighlight/generate-theme.cjs   | 177 +++++
 render-markdown-codehighlight/go.mod               |  46 ++
 render-markdown-codehighlight/go.sum               | 148 +++++
 render-markdown-codehighlight/hooks.ts             |  86 +++
 render-markdown-codehighlight/i18n/en_US.yaml      |  21 +
 render-markdown-codehighlight/i18n/index.ts        |  26 +
 render-markdown-codehighlight/i18n/translation.go  |  29 +
 render-markdown-codehighlight/i18n/zh_CN.yaml      |  21 +
 render-markdown-codehighlight/index.ts             |  33 +
 render-markdown-codehighlight/info.yaml            |  22 +
 render-markdown-codehighlight/package-lock.json    | 709 +++++++++++++++++++++
 render-markdown-codehighlight/package.json         |  47 ++
 .../render_markdown_codehighlight.go               | 106 +++
 render-markdown-codehighlight/themeColors.js       | 217 +++++++
 render-markdown-codehighlight/themeStyles.js       | 230 +++++++
 render-markdown-codehighlight/theme_list.go        |  62 ++
 render-markdown-codehighlight/tsconfig.json        |  28 +
 render-markdown-codehighlight/tsconfig.node.json   |  11 +
 render-markdown-codehighlight/vite.config.ts       |  56 ++
 22 files changed, 2102 insertions(+)

diff --git a/render-markdown-codehighlight/.eslintrc.cjs b/render-markdown-codehighlight/.eslintrc.cjs
new file mode 100644
index 0000000..d6c9537
--- /dev/null
+++ b/render-markdown-codehighlight/.eslintrc.cjs
@@ -0,0 +1,18 @@
+module.exports = {
+  root: true,
+  env: { browser: true, es2020: true },
+  extends: [
+    'eslint:recommended',
+    'plugin:@typescript-eslint/recommended',
+    'plugin:react-hooks/recommended',
+  ],
+  ignorePatterns: ['dist', '.eslintrc.cjs'],
+  parser: '@typescript-eslint/parser',
+  plugins: ['react-refresh'],
+  rules: {
+    'react-refresh/only-export-components': [
+      'warn',
+      { allowConstantExport: true },
+    ],
+  },
+}
diff --git a/render-markdown-codehighlight/.prettierrc.json b/render-markdown-codehighlight/.prettierrc.json
new file mode 100644
index 0000000..c707926
--- /dev/null
+++ b/render-markdown-codehighlight/.prettierrc.json
@@ -0,0 +1,8 @@
+{
+  "trailingComma": "all",
+  "tabWidth": 2,
+  "singleQuote": true,
+  "jsxBracketSameLine": true,
+  "printWidth": 80,
+  "endOfLine": "auto"
+}
diff --git a/render-markdown-codehighlight/README.md b/render-markdown-codehighlight/README.md
new file mode 100644
index 0000000..2253c0e
--- /dev/null
+++ b/render-markdown-codehighlight/README.md
@@ -0,0 +1 @@
+# RenderMarkdownCodehighlight Plugin
\ No newline at end of file
diff --git a/render-markdown-codehighlight/generate-theme.cjs b/render-markdown-codehighlight/generate-theme.cjs
new file mode 100644
index 0000000..e803304
--- /dev/null
+++ b/render-markdown-codehighlight/generate-theme.cjs
@@ -0,0 +1,177 @@
+const fs = require('fs');
+const path = require('path');
+
+const stylesDir = path.resolve(__dirname, 'node_modules/highlight.js/styles');
+const jsOutputFile = path.resolve(__dirname, 'themeStyles.js');
+const goOutputFile = path.resolve(__dirname, 'theme_list.go');
+const colorInfoOutputFile = path.resolve(__dirname, 'themeColors.js');
+
+// Read all CSS files from the styles directory
+let themes = fs.readdirSync(stylesDir).filter(file => file.endsWith('.css'));
+
+// Prioritize .min.css files
+const minifiedFiles = new Set(themes.filter(file => file.endsWith('.min.css')).map(file => file.replace('.min.css', '')));
+themes = themes.filter(file => {
+  const baseName = file.replace('.css', '').replace('.min', '');
+  // Skip unminified versions if corresponding .min.css file exists
+  return !minifiedFiles.has(baseName) || file.endsWith('.min.css');
+});
+
+// Group themes and classify by naming conventions
+const themeMap = {};
+let themeList = [];
+const themeColors = [];
+let defaultDarkTheme = null;
+let defaultLightTheme = null;
+
+const cssColorNames = {
+  black: '#000000',
+  white: '#ffffff',
+  navy: '#000080',
+  // Add more color names as needed if the background color in css is not defined in standard method 
+};
+
+function convertColorNameToHex(colorName) {
+  return cssColorNames[colorName.toLowerCase()] || null;
+}
+
+function normalizeHexColor(hexColor) {
+  hexColor = hexColor.startsWith('#') ? hexColor.slice(1) : hexColor;
+  if (hexColor.length === 3) {
+    hexColor = hexColor.split('').map(char => char + char).join('');
+  }
+  return hexColor;
+}
+
+function isDarkTheme(color) {
+  if (!color.startsWith('#') && !color.startsWith('rgb')) {
+    const hexColor = convertColorNameToHex(color);
+    if (hexColor) {
+      color = hexColor;
+    } else {
+      return false;
+    }
+  }
+  const hexColor = normalizeHexColor(color);
+  const rgb = parseInt(hexColor, 16);
+  const r = (rgb >> 16) & 0xff;
+  const g = (rgb >> 8) & 0xff;
+  const b = (rgb >> 0) & 0xff;
+  const brightness = (r * 299 + g * 587 + b * 114) / 1000;
+  return brightness < 128;
+}
+
+themes.forEach(file => {
+  const themeName = file.replace('.css', '').replace('.min', '');
+  const [base, ...variantParts] = themeName.split('-');
+  const variant = variantParts.join('-');
+
+  if (!themeMap[base]) {
+    themeMap[base] = {};
+  }
+
+  let isDark = false;
+  let backgroundColor = null;
+
+  if (variant.includes('light')) {
+    if (!themeMap[base].light || themeMap[base].light.length > file.length) {
+      themeMap[base].light = `() => import('highlight.js/styles/${file}?inline')`;
+      if (!defaultLightTheme) {
+        defaultLightTheme = themeMap[base].light;
+      }
+    }
+  } else if (variant.includes('dark')) {
+    if (!themeMap[base].dark || themeMap[base].dark.length > file.length) {
+      themeMap[base].dark = `() => import('highlight.js/styles/${file}?inline')`;
+      if (!defaultDarkTheme) {
+        defaultDarkTheme = themeMap[base].dark;
+      }
+    }
+  } else {
+    const cssContent = fs.readFileSync(path.resolve(stylesDir, file), 'utf-8');
+    const backgroundMatch = cssContent.match(/\.hljs\s*{[^}]*?\s*background(?:-color)?:\s*(#[0-9a-fA-F]{3,6}|rgb\([^)]+\)|[a-zA-Z]+|url\([^)]+\))/i);
+    backgroundColor = backgroundMatch ? backgroundMatch[1].trim() : null;
+
+    if (backgroundColor) {
+      if (backgroundColor.startsWith('url')) {
+        backgroundColor = null;
+      } else if (backgroundColor.startsWith('#')) {
+        isDark = isDarkTheme(backgroundColor);
+      } else if (backgroundColor.startsWith('rgb')) {
+        const rgbValues = backgroundColor.match(/\d+/g).map(Number);
+        const brightness = (rgbValues[0] * 299 + rgbValues[1] * 587 + rgbValues[2] * 114) / 1000;
+        isDark = brightness < 128;
+      } else {
+        isDark = isDarkTheme(backgroundColor);
+      }
+    }
+
+    if (isDark) {
+      if (!themeMap[base].dark || themeMap[base].dark.length > file.length) {
+        themeMap[base].dark = `() => import('highlight.js/styles/${file}?inline')`;
+        if (!defaultDarkTheme) {
+          defaultDarkTheme = themeMap[base].dark;
+        }
+      }
+    } else {
+      if (!themeMap[base].light || themeMap[base].light.length > file.length) {
+        themeMap[base].light = `() => import('highlight.js/styles/${file}?inline')`;
+        if (!defaultLightTheme) {
+          defaultLightTheme = themeMap[base].light;
+        }
+      }
+    }
+  }
+
+  if (!themeList.includes(base)) {
+    themeList.push(base);
+  }
+
+  if (backgroundColor) {
+    themeColors.push({
+      theme: base,
+      variant: isDark ? 'dark' : 'light',
+      color: backgroundColor
+    });
+  }
+});
+
+themeList = themeList.map(base => {
+  if (themeMap[base].light && !themeMap[base].dark) {
+    return `${base}-light`;
+  } else if (!themeMap[base].light && themeMap[base].dark) {
+    return `${base}-dark`;
+  } else if (themeMap[base].light && themeMap[base].dark) {
+    return `${base}-all`;
+  } else {
+    return base;
+  }
+});
+
+Object.keys(themeMap).forEach(base => {
+  if (!themeMap[base].dark && defaultDarkTheme) {
+    themeMap[base].dark = defaultDarkTheme;
+  }
+  if (!themeMap[base].light && defaultLightTheme) {
+    themeMap[base].light = defaultLightTheme;
+  }
+});
+
+const jsOutput = `export const themeStyles = {\n${Object.entries(themeMap)
+  .map(([theme, variants]) => 
+    `  ${JSON.stringify(theme)}: {\n    light: ${variants.light},\n    dark: ${variants.dark}\n  }`
+  ).join(',\n')}\n};`;
+
+fs.writeFileSync(jsOutputFile, jsOutput);
+
+const goOutput = `
+package render_markdown_codehighlight
+
+var ThemeList = []string{
+${themeList.map(theme => `"${theme}"`).join(",\n  ")},
+}
+`;
+
+fs.writeFileSync(goOutputFile, goOutput);
+
+console.log('Theme styles, Go theme list, and color information generated successfully!');
diff --git a/render-markdown-codehighlight/go.mod b/render-markdown-codehighlight/go.mod
new file mode 100644
index 0000000..9d201ed
--- /dev/null
+++ b/render-markdown-codehighlight/go.mod
@@ -0,0 +1,46 @@
+module github.com/apache/incubator-answer-plugins/render-markdown-codehighlight
+
+go 1.22.6
+
+require (
+	github.com/apache/incubator-answer v1.3.6
+	github.com/apache/incubator-answer-plugins/util v1.0.2
+)
+
+require (
+	github.com/LinkinStars/go-i18n/v2 v2.2.2 // indirect
+	github.com/aymerick/douceur v0.2.0 // indirect
+	github.com/bytedance/sonic v1.9.1 // indirect
+	github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
+	github.com/gabriel-vasile/mimetype v1.4.2 // indirect
+	github.com/gin-contrib/sse v0.1.0 // indirect
+	github.com/gin-gonic/gin v1.9.1 // indirect
+	github.com/go-playground/locales v0.14.1 // indirect
+	github.com/go-playground/universal-translator v0.18.1 // indirect
+	github.com/go-playground/validator/v10 v10.14.0 // indirect
+	github.com/goccy/go-json v0.10.2 // indirect
+	github.com/google/wire v0.5.0 // indirect
+	github.com/gorilla/css v1.0.0 // indirect
+	github.com/json-iterator/go v1.1.12 // indirect
+	github.com/klauspost/cpuid/v2 v2.2.4 // indirect
+	github.com/kr/text v0.2.0 // indirect
+	github.com/leodido/go-urn v1.2.4 // indirect
+	github.com/mattn/go-isatty v0.0.19 // indirect
+	github.com/microcosm-cc/bluemonday v1.0.21 // indirect
+	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+	github.com/modern-go/reflect2 v1.0.2 // indirect
+	github.com/pelletier/go-toml/v2 v2.0.8 // indirect
+	github.com/segmentfault/pacman v1.0.5-0.20230822083413-c0075a2d401f // indirect
+	github.com/segmentfault/pacman/contrib/i18n v0.0.0-20230516093754-b76aef1c1150 // indirect
+	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
+	github.com/ugorji/go/codec v1.2.11 // indirect
+	golang.org/x/arch v0.3.0 // indirect
+	golang.org/x/crypto v0.21.0 // indirect
+	golang.org/x/net v0.21.0 // indirect
+	golang.org/x/sys v0.18.0 // indirect
+	golang.org/x/text v0.14.0 // indirect
+	google.golang.org/protobuf v1.30.0 // indirect
+	gopkg.in/yaml.v2 v2.4.0 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+	sigs.k8s.io/yaml v1.3.0 // indirect
+)
diff --git a/render-markdown-codehighlight/go.sum b/render-markdown-codehighlight/go.sum
new file mode 100644
index 0000000..ea9c3d7
--- /dev/null
+++ b/render-markdown-codehighlight/go.sum
@@ -0,0 +1,148 @@
+github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU=
+github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/LinkinStars/go-i18n/v2 v2.2.2 h1:ZfjpzbW13dv6btv3RALKZkpN9A+7K1JA//2QcNeWaxU=
+github.com/LinkinStars/go-i18n/v2 v2.2.2/go.mod h1:hLglSJ4/3M0Y7ZVcoEJI+OwqkglHCA32DdjuJJR2LbM=
+github.com/apache/incubator-answer v1.3.6 h1:OddJdWqDrgIKY2wnLOipT3mjNI9h7fLNc4eEyyUp+hs=
+github.com/apache/incubator-answer v1.3.6/go.mod h1:YKwpG0rwRC0kHcbILcIyIbPMwsWaZ8j5lHJ34DPIdMI=
+github.com/apache/incubator-answer-plugins/util v1.0.2 h1:PontocVaiEm+oTj+4aDonwWDZnxywUeHsaTwlQgclfA=
+github.com/apache/incubator-answer-plugins/util v1.0.2/go.mod h1:KPMSiM4ec4uEl2njaGINYuSl6zVmHdvPB2nHUxVcQDo=
+github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
+github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
+github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
+github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
+github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
+github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
+github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
+github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
+github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
+github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
+github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
+github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
+github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
+github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
+github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
+github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
+github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
+github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
+github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
+github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
+github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
+github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
+github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
+github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
+github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
+github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
+github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
+github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
+github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/microcosm-cc/bluemonday v1.0.21 h1:dNH3e4PSyE4vNX+KlRGHT5KrSvjeUkoNPwEORjffHJg=
+github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
+github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
+github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
+github.com/segmentfault/pacman v1.0.5-0.20230822083413-c0075a2d401f h1:9f2Bjf6bdMvNyUop32wAGJCdp+Jdm/d6nKBYvFvkRo0=
+github.com/segmentfault/pacman v1.0.5-0.20230822083413-c0075a2d401f/go.mod h1:5lNp5REd8QMThmBUvR3Fi9Y3AsOB4GRq7soCB4QLqOs=
+github.com/segmentfault/pacman/contrib/i18n v0.0.0-20230516093754-b76aef1c1150 h1:OEuW1D7RGDE0CZDr0oGMw9Eiq7fAbD9C4WMrvSixamk=
+github.com/segmentfault/pacman/contrib/i18n v0.0.0-20230516093754-b76aef1c1150/go.mod h1:7QcRmnV7OYq4hNOOCWXT5HXnN/u756JUsqIW0Bw8n9E=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
+github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
+github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
+github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
+golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
+golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
+golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
+golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
+google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
+sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
+sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
diff --git a/render-markdown-codehighlight/hooks.ts b/render-markdown-codehighlight/hooks.ts
new file mode 100644
index 0000000..1f25f41
--- /dev/null
+++ b/render-markdown-codehighlight/hooks.ts
@@ -0,0 +1,86 @@
+import { useEffect, useState } from 'react';
+import hljs from 'highlight.js';
+import { themeStyles } from './themeStyles'
+
+
+const useHighlightCode = (element: HTMLElement | null) => {
+  const [selectTheme, setSelectTheme] = useState<string>('default');
+
+  // Fetch theme from API
+  useEffect(() => {
+    fetch('/answer/api/v1/render/config')
+      .then((response) => response.json())
+      .then((result) => {
+        console.log('Fetched theme:', result.data.select_theme);
+        setSelectTheme(result.data.select_theme);
+      })
+      .catch((error) => {
+        console.error('Error fetching theme:', error);
+      });
+  }, []);
+
+  useEffect(() => {
+    if (!element) return;
+
+    const applyThemeCSS = async (theme: string) => {
+      const existingStyleElement = document.querySelector('style[data-theme-style="highlight"]');
+      if (existingStyleElement) existingStyleElement.remove();
+
+      const styleElement = document.createElement('style');
+      styleElement.setAttribute('data-theme-style', 'highlight');
+      document.head.appendChild(styleElement);
+
+      const themeMode = theme === 'dark' ? 'dark' : 'light';
+      const selectedTheme = themeStyles[selectTheme] || themeStyles.default;
+
+      // Dynamically import the corresponding style
+      const css = await selectedTheme[themeMode]();
+      styleElement.innerHTML = css.default;
+
+      // Apply syntax highlighting
+      element.querySelectorAll('pre code').forEach((block) => {
+        hljs.highlightElement(block as HTMLElement);
+        (block as HTMLElement).style.backgroundColor = 'transparent';
+        (block as HTMLElement).style.padding = '0';
+      });
+    };
+
+    // Get and apply the initial theme
+    const currentTheme = document.documentElement.getAttribute('data-bs-theme') || 'light';
+    applyThemeCSS(currentTheme);
+
+    // Observe DOM changes (e.g., code block content changes)
+    const contentObserver = new MutationObserver(() => {
+      const newTheme = document.documentElement.getAttribute('data-bs-theme') || 'light';
+      console.log('Detected code content change, reapplying syntax highlighting, current theme:', newTheme);
+      applyThemeCSS(newTheme);
+    });
+
+    contentObserver.observe(element, {
+      childList: true, // Observe changes to child elements
+      subtree: true,   // Observe the entire subtree
+    });
+
+    // Observe theme changes
+    const themeObserver = new MutationObserver(() => {
+      const newTheme = document.documentElement.getAttribute('data-bs-theme') || 'light';
+      console.log('Detected theme change:', newTheme);
+      applyThemeCSS(newTheme);
+    });
+
+    themeObserver.observe(document.documentElement, {
+      attributes: true,
+      attributeFilter: ['data-bs-theme'],
+    });
+
+    return () => {
+      contentObserver.disconnect();
+      themeObserver.disconnect();
+    };
+  }, [element, selectTheme]);
+
+  return null;
+};
+
+export { useHighlightCode };
+
diff --git a/render-markdown-codehighlight/i18n/en_US.yaml b/render-markdown-codehighlight/i18n/en_US.yaml
new file mode 100644
index 0000000..94656b8
--- /dev/null
+++ b/render-markdown-codehighlight/i18n/en_US.yaml
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+plugin:
+  render_markdown_codehighlight:
+    backend:
+    frontend:
\ No newline at end of file
diff --git a/render-markdown-codehighlight/i18n/index.ts b/render-markdown-codehighlight/i18n/index.ts
new file mode 100644
index 0000000..7f7b453
--- /dev/null
+++ b/render-markdown-codehighlight/i18n/index.ts
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import en_US from './en_US.yaml';
+import zh_CN from './zh_CN.yaml';
+
+export default {
+  en_US,
+  zh_CN,
+};
diff --git a/render-markdown-codehighlight/i18n/translation.go b/render-markdown-codehighlight/i18n/translation.go
new file mode 100644
index 0000000..79ab843
--- /dev/null
+++ b/render-markdown-codehighlight/i18n/translation.go
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+ package i18n
+
+ const (
+	InfoName                  = "plugin.codehighlight_markdown_render.backend.info.name"
+	InfoDescription           = "plugin.codehighlight_markdown_render.backend.info.description"
+	ConfigCssFilteringTitle   = "plugin.codehighlight_markdown_render.backend.config.css_filtering.title"
+	ConfigCssFilteringLabel   = "plugin.codehighlight_markdown_render.backend.config.css_filtering.label"
+	ConfigCssFilteringTitlePrefix = "plugin.codehighlight_markdown_render.backend.config."
+ )
+ 
\ No newline at end of file
diff --git a/render-markdown-codehighlight/i18n/zh_CN.yaml b/render-markdown-codehighlight/i18n/zh_CN.yaml
new file mode 100644
index 0000000..94656b8
--- /dev/null
+++ b/render-markdown-codehighlight/i18n/zh_CN.yaml
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+plugin:
+  render_markdown_codehighlight:
+    backend:
+    frontend:
\ No newline at end of file
diff --git a/render-markdown-codehighlight/index.ts b/render-markdown-codehighlight/index.ts
new file mode 100644
index 0000000..bfc0010
--- /dev/null
+++ b/render-markdown-codehighlight/index.ts
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import i18nConfig from './i18n';
+import { useHighlightCode } from './hooks';
+import info from './info.yaml';
+
+export default {
+  info: {
+    slug_name: info.slug_name,
+    type: info.type,
+  },
+  i18nConfig,
+  hooks: {
+    useRender: [useHighlightCode],
+  },
+};
diff --git a/render-markdown-codehighlight/info.yaml b/render-markdown-codehighlight/info.yaml
new file mode 100644
index 0000000..0bcf6c7
--- /dev/null
+++ b/render-markdown-codehighlight/info.yaml
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+slug_name: render_markdown_codehighlight
+type: render
+version: 0.0.1
+author: Chen Jiaji, Zhu Xuanlyu
+link:
\ No newline at end of file
diff --git a/render-markdown-codehighlight/package-lock.json b/render-markdown-codehighlight/package-lock.json
new file mode 100644
index 0000000..e4f3946
--- /dev/null
+++ b/render-markdown-codehighlight/package-lock.json
@@ -0,0 +1,709 @@
+{
+  "name": "render-markdown-codehighlight",
+  "version": "0.0.1",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "render-markdown-codehighlight",
+      "version": "0.0.1",
+      "devDependencies": {
+        "@modyfi/vite-plugin-yaml": "^1.1.0",
+        "@typescript-eslint/eslint-plugin": "^6.0.0",
+        "@typescript-eslint/parser": "^6.0.0",
+        "@vitejs/plugin-react-swc": "^3.3.2",
+        "eslint": "^8.45.0",
+        "eslint-plugin-react-hooks": "^4.6.0",
+        "eslint-plugin-react-refresh": "^0.4.3",
+        "typescript": "^5.0.2",
+        "vite": "^4.4.5",
+        "vite-plugin-css-injected-by-js": "^3.5.1",
+        "vite-plugin-dts": "^3.9.1"
+      },
+      "peerDependencies": {
+        "react": "^18.2.0",
+        "react-bootstrap": "^2.10.0",
+        "react-dom": "^18.2.0",
+        "react-i18next": "^11.18.3"
+      }
+    },
+    "../../../node_modules/.pnpm/@modyfi+vite-plugin-yaml@1.1.0_rollup@3.29.4_vite@4.5.3_@types+node@16.11.59_sass@1.54.9_terser@5.15.0_/node_modules/@modyfi/vite-plugin-yaml": {
+      "version": "1.1.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@rollup/pluginutils": "5.1.0",
+        "js-yaml": "4.1.0",
+        "tosource": "2.0.0-alpha.3"
+      },
+      "devDependencies": {
+        "@types/js-yaml": "4.0.9",
+        "c8": "8.0.1",
+        "tsup": "8.0.1",
+        "typescript": "5.3.3",
+        "vite": "5.0.10"
+      },
+      "peerDependencies": {
+        "vite": "^3.2.7 || ^4.0.5 || ^5.0.5"
+      }
+    },
+    "../../../node_modules/.pnpm/@typescript-eslint+eslint-plugin@6.11.0_@typescript-eslint+parser@6.11.0_eslint@8.53.0_typesc_j27bwzdis2pbznfm47norch7yy/node_modules/@typescript-eslint/eslint-plugin": {
+      "version": "6.11.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@eslint-community/regexpp": "^4.5.1",
+        "@typescript-eslint/scope-manager": "6.11.0",
+        "@typescript-eslint/type-utils": "6.11.0",
+        "@typescript-eslint/utils": "6.11.0",
+        "@typescript-eslint/visitor-keys": "6.11.0",
+        "debug": "^4.3.4",
+        "graphemer": "^1.4.0",
+        "ignore": "^5.2.4",
+        "natural-compare": "^1.4.0",
+        "semver": "^7.5.4",
+        "ts-api-utils": "^1.0.1"
+      },
+      "devDependencies": {
+        "@prettier/sync": "*",
+        "@types/debug": "*",
+        "@types/marked": "*",
+        "@types/natural-compare": "*",
+        "@typescript-eslint/rule-schema-to-typescript-types": "6.11.0",
+        "@typescript-eslint/rule-tester": "6.11.0",
+        "ajv": "^6.12.6",
+        "chalk": "^5.3.0",
+        "cross-fetch": "*",
+        "grapheme-splitter": "^1.0.4",
+        "jest": "29.7.0",
+        "jest-specific-snapshot": "^8.0.0",
+        "json-schema": "*",
+        "markdown-table": "^3.0.3",
+        "marked": "^5.1.1",
+        "prettier": "^3.0.3",
+        "rimraf": "*",
+        "title-case": "^3.0.3",
+        "tsx": "*",
+        "typescript": "*"
+      },
+      "engines": {
+        "node": "^16.0.0 || >=18.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha",
+        "eslint": "^7.0.0 || ^8.0.0"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "../../../node_modules/.pnpm/@typescript-eslint+parser@6.11.0_eslint@8.53.0_typescript@5.4.2/node_modules/@typescript-eslint/parser": {
+      "version": "6.11.0",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "@typescript-eslint/scope-manager": "6.11.0",
+        "@typescript-eslint/types": "6.11.0",
+        "@typescript-eslint/typescript-estree": "6.11.0",
+        "@typescript-eslint/visitor-keys": "6.11.0",
+        "debug": "^4.3.4"
+      },
+      "devDependencies": {
+        "@types/glob": "*",
+        "downlevel-dts": "*",
+        "glob": "*",
+        "jest": "29.7.0",
+        "prettier": "^3.0.3",
+        "rimraf": "*",
+        "typescript": "*"
+      },
+      "engines": {
+        "node": "^16.0.0 || >=18.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "eslint": "^7.0.0 || ^8.0.0"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "../../../node_modules/.pnpm/@vitejs+plugin-react-swc@3.7.0_@swc+helpers@0.5.3_vite@4.5.3_@types+node@16.11.59_sass@1.54.9_terser@5.15.0_/node_modules/@vitejs/plugin-react-swc": {
+      "version": "3.7.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@swc/core": "^1.5.7"
+      },
+      "peerDependencies": {
+        "vite": "^4 || ^5"
+      }
+    },
+    "../../../node_modules/.pnpm/eslint-plugin-react-hooks@4.6.0_eslint@8.53.0/node_modules/eslint-plugin-react-hooks": {
+      "version": "4.6.0",
+      "dev": true,
+      "license": "MIT",
+      "devDependencies": {
+        "@typescript-eslint/parser-v2": "npm:@typescript-eslint/parser@^2.26.0",
+        "@typescript-eslint/parser-v3": "npm:@typescript-eslint/parser@^3.10.0",
+        "@typescript-eslint/parser-v4": "npm:@typescript-eslint/parser@^4.1.0",
+        "@typescript-eslint/parser-v5": "npm:@typescript-eslint/parser@^5.0.0-0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "peerDependencies": {
+        "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
+      }
+    },
+    "../../../node_modules/.pnpm/eslint-plugin-react-refresh@0.4.9_eslint@8.53.0/node_modules/eslint-plugin-react-refresh": {
+      "version": "0.4.9",
+      "dev": true,
+      "license": "MIT",
+      "peerDependencies": {
+        "eslint": ">=7"
+      }
+    },
+    "../../../node_modules/.pnpm/eslint@8.53.0/node_modules/eslint": {
+      "version": "8.53.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@eslint-community/eslint-utils": "^4.2.0",
+        "@eslint-community/regexpp": "^4.6.1",
+        "@eslint/eslintrc": "^2.1.3",
+        "@eslint/js": "8.53.0",
+        "@humanwhocodes/config-array": "^0.11.13",
+        "@humanwhocodes/module-importer": "^1.0.1",
+        "@nodelib/fs.walk": "^1.2.8",
+        "@ungap/structured-clone": "^1.2.0",
+        "ajv": "^6.12.4",
+        "chalk": "^4.0.0",
+        "cross-spawn": "^7.0.2",
+        "debug": "^4.3.2",
+        "doctrine": "^3.0.0",
+        "escape-string-regexp": "^4.0.0",
+        "eslint-scope": "^7.2.2",
+        "eslint-visitor-keys": "^3.4.3",
+        "espree": "^9.6.1",
+        "esquery": "^1.4.2",
+        "esutils": "^2.0.2",
+        "fast-deep-equal": "^3.1.3",
+        "file-entry-cache": "^6.0.1",
+        "find-up": "^5.0.0",
+        "glob-parent": "^6.0.2",
+        "globals": "^13.19.0",
+        "graphemer": "^1.4.0",
+        "ignore": "^5.2.0",
+        "imurmurhash": "^0.1.4",
+        "is-glob": "^4.0.0",
+        "is-path-inside": "^3.0.3",
+        "js-yaml": "^4.1.0",
+        "json-stable-stringify-without-jsonify": "^1.0.1",
+        "levn": "^0.4.1",
+        "lodash.merge": "^4.6.2",
+        "minimatch": "^3.1.2",
+        "natural-compare": "^1.4.0",
+        "optionator": "^0.9.3",
+        "strip-ansi": "^6.0.1",
+        "text-table": "^0.2.0"
+      },
+      "bin": {
+        "eslint": "bin/eslint.js"
+      },
+      "devDependencies": {
+        "@babel/core": "^7.4.3",
+        "@babel/preset-env": "^7.4.3",
+        "@wdio/browser-runner": "^8.14.6",
+        "@wdio/cli": "^8.14.6",
+        "@wdio/concise-reporter": "^8.14.0",
+        "@wdio/globals": "^8.14.6",
+        "@wdio/mocha-framework": "^8.14.0",
+        "babel-loader": "^8.0.5",
+        "c8": "^7.12.0",
+        "chai": "^4.0.1",
+        "cheerio": "^0.22.0",
+        "common-tags": "^1.8.0",
+        "core-js": "^3.1.3",
+        "ejs": "^3.0.2",
+        "eslint": "file:.",
+        "eslint-config-eslint": "file:packages/eslint-config-eslint",
+        "eslint-plugin-eslint-comments": "^3.2.0",
+        "eslint-plugin-eslint-plugin": "^5.1.0",
+        "eslint-plugin-internal-rules": "file:tools/internal-rules",
+        "eslint-plugin-jsdoc": "^46.2.5",
+        "eslint-plugin-n": "^16.0.0",
+        "eslint-plugin-unicorn": "^42.0.0",
+        "eslint-release": "^3.2.0",
+        "eslump": "^3.0.0",
+        "esprima": "^4.0.1",
+        "fast-glob": "^3.2.11",
+        "fs-teardown": "^0.1.3",
+        "glob": "^7.1.6",
+        "got": "^11.8.3",
+        "gray-matter": "^4.0.3",
+        "lint-staged": "^11.0.0",
+        "load-perf": "^0.2.0",
+        "markdownlint": "^0.25.1",
+        "markdownlint-cli": "^0.31.1",
+        "marked": "^4.0.8",
+        "memfs": "^3.0.1",
+        "mocha": "^8.3.2",
+        "mocha-junit-reporter": "^2.0.0",
+        "node-polyfill-webpack-plugin": "^1.0.3",
+        "npm-license": "^0.3.3",
+        "pirates": "^4.0.5",
+        "progress": "^2.0.3",
+        "proxyquire": "^2.0.1",
+        "recast": "^0.20.4",
+        "regenerator-runtime": "^0.13.2",
+        "rollup-plugin-node-polyfills": "^0.2.1",
+        "semver": "^7.5.3",
+        "shelljs": "^0.8.2",
+        "sinon": "^11.0.0",
+        "vite-plugin-commonjs": "^0.8.2",
+        "webdriverio": "^8.14.6",
+        "webpack": "^5.23.0",
+        "webpack-cli": "^4.5.0",
+        "yorkie": "^2.0.0"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "../../../node_modules/.pnpm/react-bootstrap@2.10.0_@types+react@18.0.20_react-dom@18.2.0_react@18.2.0__react@18.2.0/node_modules/react-bootstrap": {
+      "version": "2.10.0",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@babel/runtime": "^7.22.5",
+        "@restart/hooks": "^0.4.9",
+        "@restart/ui": "^1.6.6",
+        "@types/react-transition-group": "^4.4.6",
+        "classnames": "^2.3.2",
+        "dom-helpers": "^5.2.1",
+        "invariant": "^2.2.4",
+        "prop-types": "^15.8.1",
+        "prop-types-extra": "^1.1.0",
+        "react-transition-group": "^4.4.5",
+        "uncontrollable": "^7.2.1",
+        "warning": "^4.0.3"
+      },
+      "peerDependencies": {
+        "@types/react": ">=16.14.8",
+        "react": ">=16.14.0",
+        "react-dom": ">=16.14.0"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "../../../node_modules/.pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom": {
+      "version": "18.2.0",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "loose-envify": "^1.1.0",
+        "scheduler": "^0.23.0"
+      },
+      "peerDependencies": {
+        "react": "^18.2.0"
+      }
+    },
+    "../../../node_modules/.pnpm/react-i18next@11.18.6_i18next@21.9.2_react-dom@18.2.0_react@18.2.0__react@18.2.0/node_modules/react-i18next": {
+      "version": "11.18.6",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@babel/runtime": "^7.14.5",
+        "html-parse-stringify": "^3.0.1"
+      },
+      "devDependencies": {
+        "@babel/cli": "^7.14.5",
+        "@babel/core": "^7.14.5",
+        "@babel/plugin-proposal-async-generator-functions": "^7.14.5",
+        "@babel/plugin-proposal-object-rest-spread": "^7.14.5",
+        "@babel/plugin-transform-modules-commonjs": "^7.14.5",
+        "@babel/plugin-transform-runtime": "^7.14.5",
+        "@babel/polyfill": "^7.2.5",
+        "@babel/preset-env": "^7.14.5",
+        "@babel/preset-react": "^7.14.5",
+        "@babel/register": "^7.14.5",
+        "@testing-library/jest-dom": "^5.11.6",
+        "@testing-library/react": "^11.2.7",
+        "@testing-library/react-hooks": "^3.4.2",
+        "all-contributors-cli": "^6.20.0",
+        "babel-core": "^7.0.0-bridge.0",
+        "babel-eslint": "^10.0.3",
+        "babel-jest": "^24.8.0",
+        "babel-plugin-macros": "^2.5.0",
+        "babel-plugin-tester": "^6.0.0",
+        "coveralls": "^3.1.0",
+        "cp-cli": "^2.0.0",
+        "cross-env": "^7.0.3",
+        "dtslint": "^4.1.0",
+        "eslint": "^7.28.0",
+        "eslint-config-airbnb": "^18.2.1",
+        "eslint-config-prettier": "6.4.0",
+        "eslint-plugin-import": "^2.23.4",
+        "eslint-plugin-jest-dom": "^3.6.3",
+        "eslint-plugin-jsx-a11y": "^6.4.1",
+        "eslint-plugin-react": "^7.16.0",
+        "eslint-plugin-testing-library": "^3.10.1",
+        "husky": "^3.0.3",
+        "i18next": "^21.0.0",
+        "jest": "^24.8.0",
+        "jest-cli": "^24.8.4",
+        "lint-staged": "^8.1.3",
+        "mkdirp": "^1.0.4",
+        "prettier": "2.2.1",
+        "react": "^16.10.2",
+        "react-dom": "^16.10.2",
+        "react-test-renderer": "^17.0.1",
+        "rimraf": "2.6.3",
+        "rollup": "1.19.4",
+        "rollup-plugin-babel": "^4.3.2",
+        "rollup-plugin-commonjs": "^10.0.2",
+        "rollup-plugin-node-resolve": "^5.2.0",
+        "rollup-plugin-replace": "^2.1.0",
+        "rollup-plugin-terser": "^5.1.1",
+        "sinon": "^7.2.3",
+        "tslint": "^6.1.3",
+        "typescript": "4.6.2",
+        "yargs": "^13.3.0"
+      },
+      "peerDependencies": {
+        "i18next": ">= 19.0.0",
+        "react": ">= 16.8.0"
+      },
+      "peerDependenciesMeta": {
+        "react-dom": {
+          "optional": true
+        },
+        "react-native": {
+          "optional": true
+        }
+      }
+    },
+    "../../../node_modules/.pnpm/react@18.2.0/node_modules/react": {
+      "version": "18.2.0",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "loose-envify": "^1.1.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "../../../node_modules/.pnpm/typescript@5.4.2/node_modules/typescript": {
+      "version": "5.4.2",
+      "dev": true,
+      "license": "Apache-2.0",
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "devDependencies": {
+        "@esfx/canceltoken": "^1.0.0",
+        "@octokit/rest": "^20.0.2",
+        "@types/chai": "^4.3.11",
+        "@types/glob": "^8.1.0",
+        "@types/microsoft__typescript-etw": "^0.1.3",
+        "@types/minimist": "^1.2.5",
+        "@types/mocha": "^10.0.6",
+        "@types/ms": "^0.7.34",
+        "@types/node": "latest",
+        "@types/source-map-support": "^0.5.10",
+        "@types/which": "^3.0.3",
+        "@typescript-eslint/eslint-plugin": "^6.19.0",
+        "@typescript-eslint/parser": "^6.19.0",
+        "@typescript-eslint/utils": "^6.19.0",
+        "azure-devops-node-api": "^12.3.0",
+        "c8": "^9.1.0",
+        "chai": "^4.4.1",
+        "chalk": "^4.1.2",
+        "chokidar": "^3.5.3",
+        "diff": "^5.1.0",
+        "dprint": "^0.45.0",
+        "esbuild": "^0.20.0",
+        "eslint": "^8.56.0",
+        "eslint-formatter-autolinkable-stylish": "^1.3.0",
+        "eslint-plugin-local": "^3.1.0",
+        "eslint-plugin-no-null": "^1.0.2",
+        "eslint-plugin-simple-import-sort": "^10.0.0",
+        "fast-xml-parser": "^4.3.3",
+        "glob": "^10.3.10",
+        "hereby": "^1.8.9",
+        "jsonc-parser": "^3.2.0",
+        "minimist": "^1.2.8",
+        "mocha": "^10.2.0",
+        "mocha-fivemat-progress-reporter": "^0.1.0",
+        "ms": "^2.1.3",
+        "node-fetch": "^3.3.2",
+        "playwright": "^1.41.0",
+        "source-map-support": "^0.5.21",
+        "tslib": "^2.6.2",
+        "typescript": "5.4.0-dev.20240119",
+        "which": "^3.0.1"
+      },
+      "engines": {
+        "node": ">=14.17"
+      }
+    },
+    "../../../node_modules/.pnpm/vite-plugin-dts@3.9.1_@types+node@16.11.59_rollup@3.29.4_typescript@5.4.2_vite@4.5.3_@types+n_ufetuueabzabk4d7dqgvhiagly/node_modules/vite-plugin-dts": {
+      "version": "3.9.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@microsoft/api-extractor": "7.43.0",
+        "@rollup/pluginutils": "^5.1.0",
+        "@vue/language-core": "^1.8.27",
+        "debug": "^4.3.4",
+        "kolorist": "^1.8.0",
+        "magic-string": "^0.30.8",
+        "vue-tsc": "^1.8.27"
+      },
+      "devDependencies": {
+        "@commitlint/cli": "^19.2.1",
+        "@types/debug": "^4.1.12",
+        "@types/minimist": "^1.2.5",
+        "@types/node": "^20.11.30",
+        "@types/prompts": "^2.4.9",
+        "@types/semver": "^7.5.8",
+        "@vexip-ui/commitlint-config": "^0.4.0",
+        "@vexip-ui/eslint-config": "^0.12.0",
+        "@vexip-ui/prettier-config": "^0.2.0",
+        "@vue/eslint-config-standard": "^8.0.1",
+        "@vue/eslint-config-typescript": "^13.0.0",
+        "conventional-changelog-cli": "^4.1.0",
+        "eslint": "^8.57.0",
+        "execa": "^8.0.1",
+        "husky": "^9.0.11",
+        "is-ci": "^3.0.1",
+        "lint-staged": "^15.2.2",
+        "minimist": "^1.2.8",
+        "pinst": "^3.0.0",
+        "prettier": "^3.2.5",
+        "pretty-quick": "^4.0.0",
+        "prompts": "^2.4.2",
+        "rimraf": "^5.0.5",
+        "semver": "^7.6.0",
+        "tsx": "^4.7.1",
+        "typescript": "5.4.3",
+        "unbuild": "^2.0.0",
+        "vite": "^5.2.6",
+        "vitest": "^1.4.0"
+      },
+      "engines": {
+        "node": "^14.18.0 || >=16.0.0"
+      },
+      "peerDependencies": {
+        "typescript": "*",
+        "vite": "*"
+      },
+      "peerDependenciesMeta": {
+        "vite": {
+          "optional": true
+        }
+      }
+    },
+    "../../../node_modules/.pnpm/vite@4.5.3_@types+node@16.11.59_sass@1.54.9_terser@5.15.0/node_modules/vite": {
+      "version": "4.5.3",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "esbuild": "^0.18.10",
+        "postcss": "^8.4.27",
+        "rollup": "^3.27.1"
+      },
+      "bin": {
+        "vite": "bin/vite.js"
+      },
+      "devDependencies": {
+        "@ampproject/remapping": "^2.2.1",
+        "@babel/parser": "^7.22.7",
+        "@babel/types": "^7.22.5",
+        "@jridgewell/trace-mapping": "^0.3.18",
+        "@rollup/plugin-alias": "^4.0.4",
+        "@rollup/plugin-commonjs": "^25.0.3",
+        "@rollup/plugin-dynamic-import-vars": "^2.0.4",
+        "@rollup/plugin-json": "^6.0.0",
+        "@rollup/plugin-node-resolve": "15.1.0",
+        "@rollup/plugin-typescript": "^11.1.2",
+        "@rollup/pluginutils": "^5.0.2",
+        "@types/escape-html": "^1.0.2",
+        "@types/pnpapi": "^0.0.2",
+        "acorn": "^8.10.0",
+        "acorn-walk": "^8.2.0",
+        "cac": "^6.7.14",
+        "chokidar": "^3.5.3",
+        "connect": "^3.7.0",
+        "connect-history-api-fallback": "^2.0.0",
+        "convert-source-map": "^2.0.0",
+        "cors": "^2.8.5",
+        "cross-spawn": "^7.0.3",
+        "debug": "^4.3.4",
+        "dep-types": "link:./src/types",
+        "dotenv": "^16.3.1",
+        "dotenv-expand": "^9.0.0",
+        "es-module-lexer": "^1.3.0",
+        "escape-html": "^1.0.3",
+        "estree-walker": "^3.0.3",
+        "etag": "^1.8.1",
+        "fast-glob": "^3.3.1",
+        "http-proxy": "^1.18.1",
+        "json-stable-stringify": "^1.0.2",
+        "launch-editor-middleware": "^2.6.0",
+        "lightningcss": "^1.21.5",
+        "magic-string": "^0.30.2",
+        "micromatch": "^4.0.5",
+        "mlly": "^1.4.0",
+        "mrmime": "^1.0.1",
+        "okie": "^1.0.1",
+        "open": "^8.4.2",
+        "parse5": "^7.1.2",
+        "periscopic": "^3.1.0",
+        "picocolors": "^1.0.0",
+        "picomatch": "^2.3.1",
+        "postcss-import": "^15.1.0",
+        "postcss-load-config": "^4.0.1",
+        "postcss-modules": "^6.0.0",
+        "resolve.exports": "^2.0.2",
+        "rollup-plugin-license": "^3.0.1",
+        "sirv": "^2.0.3",
+        "source-map-support": "^0.5.21",
+        "strip-ansi": "^7.1.0",
+        "strip-literal": "^1.3.0",
+        "tsconfck": "^2.1.2",
+        "tslib": "^2.6.1",
+        "types": "link:./types",
+        "ufo": "^1.2.0",
+        "ws": "^8.13.0"
+      },
+      "engines": {
+        "node": "^14.18.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/vitejs/vite?sponsor=1"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.2"
+      },
+      "peerDependencies": {
+        "@types/node": ">= 14",
+        "less": "*",
+        "lightningcss": "^1.21.0",
+        "sass": "*",
+        "stylus": "*",
+        "sugarss": "*",
+        "terser": "^5.4.0"
+      },
+      "peerDependenciesMeta": {
+        "@types/node": {
+          "optional": true
+        },
+        "less": {
+          "optional": true
+        },
+        "lightningcss": {
+          "optional": true
+        },
+        "sass": {
+          "optional": true
+        },
+        "stylus": {
+          "optional": true
+        },
+        "sugarss": {
+          "optional": true
+        },
+        "terser": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@modyfi/vite-plugin-yaml": {
+      "resolved": "../../../node_modules/.pnpm/@modyfi+vite-plugin-yaml@1.1.0_rollup@3.29.4_vite@4.5.3_@types+node@16.11.59_sass@1.54.9_terser@5.15.0_/node_modules/@modyfi/vite-plugin-yaml",
+      "link": true
+    },
+    "node_modules/@typescript-eslint/eslint-plugin": {
+      "resolved": "../../../node_modules/.pnpm/@typescript-eslint+eslint-plugin@6.11.0_@typescript-eslint+parser@6.11.0_eslint@8.53.0_typesc_j27bwzdis2pbznfm47norch7yy/node_modules/@typescript-eslint/eslint-plugin",
+      "link": true
+    },
+    "node_modules/@typescript-eslint/parser": {
+      "resolved": "../../../node_modules/.pnpm/@typescript-eslint+parser@6.11.0_eslint@8.53.0_typescript@5.4.2/node_modules/@typescript-eslint/parser",
+      "link": true
+    },
+    "node_modules/@vitejs/plugin-react-swc": {
+      "resolved": "../../../node_modules/.pnpm/@vitejs+plugin-react-swc@3.7.0_@swc+helpers@0.5.3_vite@4.5.3_@types+node@16.11.59_sass@1.54.9_terser@5.15.0_/node_modules/@vitejs/plugin-react-swc",
+      "link": true
+    },
+    "node_modules/eslint": {
+      "resolved": "../../../node_modules/.pnpm/eslint@8.53.0/node_modules/eslint",
+      "link": true
+    },
+    "node_modules/eslint-plugin-react-hooks": {
+      "resolved": "../../../node_modules/.pnpm/eslint-plugin-react-hooks@4.6.0_eslint@8.53.0/node_modules/eslint-plugin-react-hooks",
+      "link": true
+    },
+    "node_modules/eslint-plugin-react-refresh": {
+      "resolved": "../../../node_modules/.pnpm/eslint-plugin-react-refresh@0.4.9_eslint@8.53.0/node_modules/eslint-plugin-react-refresh",
+      "link": true
+    },
+    "node_modules/react": {
+      "resolved": "../../../node_modules/.pnpm/react@18.2.0/node_modules/react",
+      "link": true
+    },
+    "node_modules/react-bootstrap": {
+      "resolved": "../../../node_modules/.pnpm/react-bootstrap@2.10.0_@types+react@18.0.20_react-dom@18.2.0_react@18.2.0__react@18.2.0/node_modules/react-bootstrap",
+      "link": true
+    },
+    "node_modules/react-dom": {
+      "resolved": "../../../node_modules/.pnpm/react-dom@18.2.0_react@18.2.0/node_modules/react-dom",
+      "link": true
+    },
+    "node_modules/react-i18next": {
+      "resolved": "../../../node_modules/.pnpm/react-i18next@11.18.6_i18next@21.9.2_react-dom@18.2.0_react@18.2.0__react@18.2.0/node_modules/react-i18next",
+      "link": true
+    },
+    "node_modules/typescript": {
+      "resolved": "../../../node_modules/.pnpm/typescript@5.4.2/node_modules/typescript",
+      "link": true
+    },
+    "node_modules/vite": {
+      "resolved": "../../../node_modules/.pnpm/vite@4.5.3_@types+node@16.11.59_sass@1.54.9_terser@5.15.0/node_modules/vite",
+      "link": true
+    },
+    "node_modules/vite-plugin-css-injected-by-js": {
+      "version": "3.5.1",
+      "resolved": "https://registry.npmjs.org/vite-plugin-css-injected-by-js/-/vite-plugin-css-injected-by-js-3.5.1.tgz",
+      "integrity": "sha512-9ioqwDuEBxW55gNoWFEDhfLTrVKXEEZgl5adhWmmqa88EQGKfTmexy4v1Rh0pAS6RhKQs2bUYQArprB32JpUZQ==",
+      "dev": true,
+      "license": "MIT",
+      "peerDependencies": {
+        "vite": ">2.0.0-0"
+      }
+    },
+    "node_modules/vite-plugin-dts": {
+      "resolved": "../../../node_modules/.pnpm/vite-plugin-dts@3.9.1_@types+node@16.11.59_rollup@3.29.4_typescript@5.4.2_vite@4.5.3_@types+n_ufetuueabzabk4d7dqgvhiagly/node_modules/vite-plugin-dts",
+      "link": true
+    }
+  }
+}
diff --git a/render-markdown-codehighlight/package.json b/render-markdown-codehighlight/package.json
new file mode 100644
index 0000000..56a2f32
--- /dev/null
+++ b/render-markdown-codehighlight/package.json
@@ -0,0 +1,47 @@
+{
+  "name": "render-markdown-codehighlight",
+  "version": "0.0.1",
+  "description": "",
+  "type": "module",
+  "files": [
+    "dist",
+    "README.md"
+  ],
+  "main": "./dist/render-markdown-codehighlight.umd.js",
+  "module": "./dist/render-markdown-codehighlight.es.js",
+  "types": "./dist/render-markdown-codehighlight.d.ts",
+  "exports": {
+    ".": {
+      "import": "./dist/render-markdown-codehighlight.es.js",
+      "require": "./dist/render-markdown-codehighlight.umd.js"
+    }
+  },
+  "scripts": {
+    "dev": "vite build --mode development --watch",
+    "build": "tsc && vite build",
+    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
+    "postinstall": "node ./generate-theme.cjs"
+  },
+  "peerDependencies": {
+    "react": "^18.2.0",
+    "react-bootstrap": "^2.10.0",
+    "react-dom": "^18.2.0",
+    "react-i18next": "^11.18.3"
+  },
+  "devDependencies": {
+    "@modyfi/vite-plugin-yaml": "^1.1.0",
+    "@typescript-eslint/eslint-plugin": "^6.0.0",
+    "@typescript-eslint/parser": "^6.0.0",
+    "@vitejs/plugin-react-swc": "^3.3.2",
+    "eslint": "^8.45.0",
+    "eslint-plugin-react-hooks": "^4.6.0",
+    "eslint-plugin-react-refresh": "^0.4.3",
+    "typescript": "^5.0.2",
+    "vite": "^4.4.5",
+    "vite-plugin-css-injected-by-js": "^3.5.1",
+    "vite-plugin-dts": "^3.9.1"
+  },
+  "dependencies": {
+    "highlight.js": "^11.10.0"
+  }
+}
diff --git a/render-markdown-codehighlight/render_markdown_codehighlight.go b/render-markdown-codehighlight/render_markdown_codehighlight.go
new file mode 100644
index 0000000..285e0fa
--- /dev/null
+++ b/render-markdown-codehighlight/render_markdown_codehighlight.go
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+ package render_markdown_codehighlight
+
+ import (
+	 "embed"
+	 "encoding/json"
+     "log"
+	 "github.com/gin-gonic/gin"
+     "strings" 
+	 "github.com/apache/incubator-answer-plugins/render-markdown-codehighlight/i18n"
+	 "github.com/apache/incubator-answer-plugins/util"
+	 "github.com/apache/incubator-answer/plugin"
+ )
+ 
+ //go:embed info.yaml
+ var Info embed.FS
+ 
+ type Render struct {
+	 Config *RenderConfig
+ }
+ 
+ type RenderConfig struct {
+	 SelectTheme string `json:"select_theme"`
+ }
+ 
+ func init() {
+	 plugin.Register(&Render{
+		 Config: &RenderConfig{},
+	 })
+ }
+ 
+ func (r *Render) Info() plugin.Info {
+	 info := &util.Info{}
+	 info.GetInfo(Info)
+ 
+	 return plugin.Info{
+		 Name:        plugin.MakeTranslator(i18n.InfoName),
+		 SlugName:    info.SlugName,
+		 Description: plugin.MakeTranslator(i18n.InfoDescription),
+		 Author:      info.Author,
+		 Version:     info.Version,
+		 Link:        info.Link,
+	 }
+ }
+
+ func (r *Render) ConfigFields() []plugin.ConfigField {
+	themeOptions := make([]plugin.ConfigFieldOption, len(ThemeList))
+
+	for i, theme := range ThemeList {
+		// Split the theme string by the hyphen and take the first part
+		themeParts := strings.Split(theme, "-")
+		themeValue := themeParts[0]
+
+		themeOptions[i] = plugin.ConfigFieldOption{
+			Value: themeValue, // Use the first part as the Value
+			Label: plugin.MakeTranslator(i18n.ConfigCssFilteringTitlePrefix + theme),
+		}
+	}
+
+	return []plugin.ConfigField{
+		{
+			Name:      "select_theme",
+			Type:      plugin.ConfigTypeSelect,
+			Title:     plugin.MakeTranslator(i18n.ConfigCssFilteringTitle),
+			Required:  false,
+			UIOptions: plugin.ConfigFieldUIOptions{},
+			Value:     r.Config.SelectTheme,
+			Options:   themeOptions,
+		},
+	}
+}
+ 
+ func (r *Render) ConfigReceiver(config []byte) error {
+	 c := &RenderConfig{}
+	 _ = json.Unmarshal(config, c)
+	 r.Config = c
+	 log.Println("Received theme:", r.Config.SelectTheme) 
+	 return nil
+ }
+ 
+ func (r *Render) GetRenderConfig(ctx *gin.Context) (renderConfig *plugin.RenderConfig) {
+	     log.Println("Current theme:", r.Config.SelectTheme) 
+	     renderConfig = &plugin.RenderConfig{
+		 SelectTheme: r.Config.SelectTheme,
+	 }
+	 return
+ }
+ 
diff --git a/render-markdown-codehighlight/themeColors.js b/render-markdown-codehighlight/themeColors.js
new file mode 100644
index 0000000..10086e7
--- /dev/null
+++ b/render-markdown-codehighlight/themeColors.js
@@ -0,0 +1,217 @@
+export const themeColors = [
+  {
+    "theme": "agate",
+    "variant": "dark",
+    "color": "#333"
+  },
+  {
+    "theme": "an",
+    "variant": "dark",
+    "color": "#1c1d21"
+  },
+  {
+    "theme": "androidstudio",
+    "variant": "dark",
+    "color": "#282b2e"
+  },
+  {
+    "theme": "arta",
+    "variant": "dark",
+    "color": "#222"
+  },
+  {
+    "theme": "ascetic",
+    "variant": "light",
+    "color": "#fff"
+  },
+  {
+    "theme": "codepen",
+    "variant": "dark",
+    "color": "#222"
+  },
+  {
+    "theme": "color",
+    "variant": "light",
+    "color": "#fff"
+  },
+  {
+    "theme": "dark",
+    "variant": "dark",
+    "color": "#303030"
+  },
+  {
+    "theme": "default",
+    "variant": "light",
+    "color": "#f3f3f3"
+  },
+  {
+    "theme": "devibeans",
+    "variant": "dark",
+    "color": "#000"
+  },
+  {
+    "theme": "docco",
+    "variant": "light",
+    "color": "#f8f8ff"
+  },
+  {
+    "theme": "far",
+    "variant": "dark",
+    "color": "navy"
+  },
+  {
+    "theme": "felipec",
+    "variant": "dark",
+    "color": "#1e1e22"
+  },
+  {
+    "theme": "foundation",
+    "variant": "light",
+    "color": "#eee"
+  },
+  {
+    "theme": "github",
+    "variant": "light",
+    "color": "#fff"
+  },
+  {
+    "theme": "gml",
+    "variant": "dark",
+    "color": "#222"
+  },
+  {
+    "theme": "googlecode",
+    "variant": "light",
+    "color": "#fff"
+  },
+  {
+    "theme": "grayscale",
+    "variant": "light",
+    "color": "#fff"
+  },
+  {
+    "theme": "hybrid",
+    "variant": "dark",
+    "color": "#1d1f21"
+  },
+  {
+    "theme": "idea",
+    "variant": "light",
+    "color": "#fff"
+  },
+  {
+    "theme": "ir",
+    "variant": "dark",
+    "color": "#000"
+  },
+  {
+    "theme": "lightfair",
+    "variant": "light",
+    "color": "#fff"
+  },
+  {
+    "theme": "lioshi",
+    "variant": "dark",
+    "color": "#303030"
+  },
+  {
+    "theme": "magula",
+    "variant": "light",
+    "color": "#f4f4f4"
+  },
+  {
+    "theme": "mono",
+    "variant": "light",
+    "color": "#eaeef3"
+  },
+  {
+    "theme": "monokai",
+    "variant": "dark",
+    "color": "#23241f"
+  },
+  {
+    "theme": "monokai",
+    "variant": "dark",
+    "color": "#272822"
+  },
+  {
+    "theme": "night",
+    "variant": "dark",
+    "color": "#011627"
+  },
+  {
+    "theme": "nord",
+    "variant": "dark",
+    "color": "#2e3440"
+  },
+  {
+    "theme": "obsidian",
+    "variant": "dark",
+    "color": "#282b2e"
+  },
+  {
+    "theme": "purebasic",
+    "variant": "light",
+    "color": "#ffffdf"
+  },
+  {
+    "theme": "rainbow",
+    "variant": "dark",
+    "color": "#474949"
+  },
+  {
+    "theme": "routeros",
+    "variant": "light",
+    "color": "#f0f0f0"
+  },
+  {
+    "theme": "school",
+    "variant": "light",
+    "color": "#f6f5b2"
+  },
+  {
+    "theme": "shades",
+    "variant": "dark",
+    "color": "#2d2b57"
+  },
+  {
+    "theme": "srcery",
+    "variant": "dark",
+    "color": "#1c1b19"
+  },
+  {
+    "theme": "sunburst",
+    "variant": "dark",
+    "color": "#000"
+  },
+  {
+    "theme": "tomorrow",
+    "variant": "dark",
+    "color": "#002451"
+  },
+  {
+    "theme": "tomorrow",
+    "variant": "dark",
+    "color": "#000"
+  },
+  {
+    "theme": "vs",
+    "variant": "light",
+    "color": "#fff"
+  },
+  {
+    "theme": "vs2015",
+    "variant": "dark",
+    "color": "#1e1e1e"
+  },
+  {
+    "theme": "xcode",
+    "variant": "light",
+    "color": "#fff"
+  },
+  {
+    "theme": "xt256",
+    "variant": "dark",
+    "color": "#000"
+  }
+];
\ No newline at end of file
diff --git a/render-markdown-codehighlight/themeStyles.js b/render-markdown-codehighlight/themeStyles.js
new file mode 100644
index 0000000..e4e3bdd
--- /dev/null
+++ b/render-markdown-codehighlight/themeStyles.js
@@ -0,0 +1,230 @@
+export const themeStyles = {
+  "1c": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "a11y": {
+    light: () => import('highlight.js/styles/a11y-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "agate": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/agate.min.css?inline')
+  },
+  "an": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/an-old-hope.min.css?inline')
+  },
+  "androidstudio": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/androidstudio.min.css?inline')
+  },
+  "arduino": {
+    light: () => import('highlight.js/styles/arduino-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "arta": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/arta.min.css?inline')
+  },
+  "ascetic": {
+    light: () => import('highlight.js/styles/ascetic.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "atom": {
+    light: () => import('highlight.js/styles/atom-one-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/atom-one-dark.min.css?inline')
+  },
+  "brown": {
+    light: () => import('highlight.js/styles/brown-paper.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "codepen": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/codepen-embed.min.css?inline')
+  },
+  "color": {
+    light: () => import('highlight.js/styles/color-brewer.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "dark": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/dark.min.css?inline')
+  },
+  "default": {
+    light: () => import('highlight.js/styles/default.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "devibeans": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/devibeans.min.css?inline')
+  },
+  "docco": {
+    light: () => import('highlight.js/styles/docco.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "far": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/far.min.css?inline')
+  },
+  "felipec": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/felipec.min.css?inline')
+  },
+  "foundation": {
+    light: () => import('highlight.js/styles/foundation.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "github": {
+    light: () => import('highlight.js/styles/github.min.css?inline'),
+    dark: () => import('highlight.js/styles/github-dark.min.css?inline')
+  },
+  "gml": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/gml.min.css?inline')
+  },
+  "googlecode": {
+    light: () => import('highlight.js/styles/googlecode.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "gradient": {
+    light: () => import('highlight.js/styles/gradient-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/gradient-dark.min.css?inline')
+  },
+  "grayscale": {
+    light: () => import('highlight.js/styles/grayscale.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "hybrid": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/hybrid.min.css?inline')
+  },
+  "idea": {
+    light: () => import('highlight.js/styles/idea.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "intellij": {
+    light: () => import('highlight.js/styles/intellij-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "ir": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/ir-black.min.css?inline')
+  },
+  "isbl": {
+    light: () => import('highlight.js/styles/isbl-editor-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/isbl-editor-dark.min.css?inline')
+  },
+  "kimbie": {
+    light: () => import('highlight.js/styles/kimbie-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/kimbie-dark.min.css?inline')
+  },
+  "lightfair": {
+    light: () => import('highlight.js/styles/lightfair.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "lioshi": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/lioshi.min.css?inline')
+  },
+  "magula": {
+    light: () => import('highlight.js/styles/magula.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "mono": {
+    light: () => import('highlight.js/styles/mono-blue.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "monokai": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/monokai.min.css?inline')
+  },
+  "night": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/night-owl.min.css?inline')
+  },
+  "nnfx": {
+    light: () => import('highlight.js/styles/nnfx-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/nnfx-dark.min.css?inline')
+  },
+  "nord": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/nord.min.css?inline')
+  },
+  "obsidian": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/obsidian.min.css?inline')
+  },
+  "panda": {
+    light: () => import('highlight.js/styles/panda-syntax-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/panda-syntax-dark.min.css?inline')
+  },
+  "paraiso": {
+    light: () => import('highlight.js/styles/paraiso-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/paraiso-dark.min.css?inline')
+  },
+  "pojoaque": {
+    light: () => import('highlight.js/styles/pojoaque.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "purebasic": {
+    light: () => import('highlight.js/styles/purebasic.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "qtcreator": {
+    light: () => import('highlight.js/styles/qtcreator-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/qtcreator-dark.min.css?inline')
+  },
+  "rainbow": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/rainbow.min.css?inline')
+  },
+  "routeros": {
+    light: () => import('highlight.js/styles/routeros.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "school": {
+    light: () => import('highlight.js/styles/school-book.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "shades": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/shades-of-purple.min.css?inline')
+  },
+  "srcery": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/srcery.min.css?inline')
+  },
+  "stackoverflow": {
+    light: () => import('highlight.js/styles/stackoverflow-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/stackoverflow-dark.min.css?inline')
+  },
+  "sunburst": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/sunburst.min.css?inline')
+  },
+  "tokyo": {
+    light: () => import('highlight.js/styles/tokyo-night-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/tokyo-night-dark.min.css?inline')
+  },
+  "tomorrow": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/tomorrow-night-bright.min.css?inline')
+  },
+  "vs": {
+    light: () => import('highlight.js/styles/vs.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "vs2015": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/vs2015.min.css?inline')
+  },
+  "xcode": {
+    light: () => import('highlight.js/styles/xcode.min.css?inline'),
+    dark: () => import('highlight.js/styles/a11y-dark.min.css?inline')
+  },
+  "xt256": {
+    light: () => import('highlight.js/styles/1c-light.min.css?inline'),
+    dark: () => import('highlight.js/styles/xt256.min.css?inline')
+  }
+};
\ No newline at end of file
diff --git a/render-markdown-codehighlight/theme_list.go b/render-markdown-codehighlight/theme_list.go
new file mode 100644
index 0000000..831b2f2
--- /dev/null
+++ b/render-markdown-codehighlight/theme_list.go
@@ -0,0 +1,62 @@
+
+package render_markdown_codehighlight
+
+var ThemeList = []string{
+"1c-light",
+  "a11y-all",
+  "agate-dark",
+  "an-dark",
+  "androidstudio-dark",
+  "arduino-light",
+  "arta-dark",
+  "ascetic-light",
+  "atom-all",
+  "brown-light",
+  "codepen-dark",
+  "color-light",
+  "dark-dark",
+  "default-light",
+  "devibeans-dark",
+  "docco-light",
+  "far-dark",
+  "felipec-dark",
+  "foundation-light",
+  "github-all",
+  "gml-dark",
+  "googlecode-light",
+  "gradient-all",
+  "grayscale-light",
+  "hybrid-dark",
+  "idea-light",
+  "intellij-light",
+  "ir-dark",
+  "isbl-all",
+  "kimbie-all",
+  "lightfair-light",
+  "lioshi-dark",
+  "magula-light",
+  "mono-light",
+  "monokai-dark",
+  "night-dark",
+  "nnfx-all",
+  "nord-dark",
+  "obsidian-dark",
+  "panda-all",
+  "paraiso-all",
+  "pojoaque-light",
+  "purebasic-light",
+  "qtcreator-all",
+  "rainbow-dark",
+  "routeros-light",
+  "school-light",
+  "shades-dark",
+  "srcery-dark",
+  "stackoverflow-all",
+  "sunburst-dark",
+  "tokyo-all",
+  "tomorrow-dark",
+  "vs-light",
+  "vs2015-dark",
+  "xcode-light",
+  "xt256-dark",
+}
diff --git a/render-markdown-codehighlight/tsconfig.json b/render-markdown-codehighlight/tsconfig.json
new file mode 100644
index 0000000..8308948
--- /dev/null
+++ b/render-markdown-codehighlight/tsconfig.json
@@ -0,0 +1,28 @@
+{
+  "compilerOptions": {
+    "target": "ES2020",
+    "useDefineForClassFields": true,
+    "lib": ["ES2020", "DOM", "DOM.Iterable"],
+    "module": "ESNext",
+    "skipLibCheck": true,
+
+    /* Bundler mode */
+    "moduleResolution": "bundler",
+    "allowImportingTsExtensions": true,
+    "resolveJsonModule": true,
+    "isolatedModules": true,
+    "noEmit": true,
+    "jsx": "react-jsx",
+
+    /* Linting */
+    "strict": true,
+    "noUnusedLocals": true,
+    "noUnusedParameters": true,
+    "noFallthroughCasesInSwitch": true,
+    "types": [
+      "@modyfi/vite-plugin-yaml/modules"
+    ]
+  },
+  "include": ["src"],
+  "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/render-markdown-codehighlight/tsconfig.node.json b/render-markdown-codehighlight/tsconfig.node.json
new file mode 100644
index 0000000..97ede7e
--- /dev/null
+++ b/render-markdown-codehighlight/tsconfig.node.json
@@ -0,0 +1,11 @@
+{
+  "compilerOptions": {
+    "composite": true,
+    "skipLibCheck": true,
+    "module": "ESNext",
+    "moduleResolution": "bundler",
+    "allowSyntheticDefaultImports": true,
+    "strict": true
+  },
+  "include": ["vite.config.ts"]
+}
diff --git a/render-markdown-codehighlight/vite.config.ts b/render-markdown-codehighlight/vite.config.ts
new file mode 100644
index 0000000..ca1fe1d
--- /dev/null
+++ b/render-markdown-codehighlight/vite.config.ts
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react-swc';
+import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'
+import ViteYaml from '@modyfi/vite-plugin-yaml';
+import dts from 'vite-plugin-dts';
+import packageJson from './package.json';
+
+// https://vitejs.dev/config/
+export default defineConfig({
+  plugins: [
+    react(),
+    ViteYaml(),
+    cssInjectedByJsPlugin(),
+    dts({
+      insertTypesEntry: true,
+    }),
+  ],
+  build: {
+    lib: {
+      entry: 'index.ts',
+      name: packageJson.name,
+      fileName: (format) => `${packageJson.name}.${format}.js`,
+    },
+    rollupOptions: {
+      external: ['react', 'react-dom', 'react-i18next', 'react-bootstrap', 'highlight.js'],
+      output: {
+        globals: {
+          react: 'React',
+          'react-dom': 'ReactDOM',
+          'react-i18next': 'reactI18next',
+          'react-bootstrap': 'reactBootstrap',
+          'highlight.js': 'highlight.js',
+        },
+      },
+    },
+  },
+});