diff --git a/docs/bash.md b/docs/bash.md
index 19b4d21..4dabb37 100644
--- a/docs/bash.md
+++ b/docs/bash.md
@@ -34,11 +34,9 @@ NAME = "John"   # => Error (关于空间)
 
 ### 注释
 
-```bash
-# 这是一个内联 Bash 注释。
-```
-
 ```shell
+# 这是一个内联 Bash 注释。
+
 : '
 这是一个
 非常整洁的评论
diff --git a/scripts/assets/menu.svg b/scripts/assets/menu.svg
new file mode 100644
index 0000000..c9be56e
--- /dev/null
+++ b/scripts/assets/menu.svg
@@ -0,0 +1,3 @@
+<svg aria-hidden="true" fill="currentColor" height="1em" width="1em" viewBox="0 0 16 16" version="1.1" data-view-component="true">
+  <path fill-rule="evenodd" d="M2 4a1 1 0 100-2 1 1 0 000 2zm3.75-1.5a.75.75 0 000 1.5h8.5a.75.75 0 000-1.5h-8.5zm0 5a.75.75 0 000 1.5h8.5a.75.75 0 000-1.5h-8.5zm0 5a.75.75 0 000 1.5h8.5a.75.75 0 000-1.5h-8.5zM3 8a1 1 0 11-2 0 1 1 0 012 0zm-1 6a1 1 0 100-2 1 1 0 000 2z"></path>
+</svg>
\ No newline at end of file
diff --git a/scripts/create.mjs b/scripts/create.mjs
index 30a5564..256ade6 100644
--- a/scripts/create.mjs
+++ b/scripts/create.mjs
@@ -1,6 +1,9 @@
 import markdown from '@wcj/markdown-to-html';
 import rehypeDocument from 'rehype-document';
 import remarkGemoji from 'remark-gemoji';
+import rehypeRaw from 'rehype-raw';
+import rehypeAttrs from 'rehype-attr';
+import rehypeKatex from 'rehype-katex';
 import rehypeAutolinkHeadings from 'rehype-autolink-headings';
 import rehypeSlug from 'rehype-slug';
 import { htmlTagAddAttri } from './nodes/htmlTagAddAttri.mjs';
@@ -9,7 +12,7 @@ import { header } from './nodes/header.mjs';
 import { rehypeUrls } from './utils/rehypeUrls.mjs';
 import { tooltips } from './utils/tooltips.mjs';
 import { homeCardIcons } from './utils/homeCardIcons.mjs';
-import { getTocsTree } from './utils/getTocsTree.mjs';
+import { getTocsTree, getTocsTitleNode, getTocsTitleNodeWarpper, addTocsInWarp } from './utils/getTocsTree.mjs';
 import { rehypeTitle } from './utils/rehypeTitle.mjs';
 import { anchorPoint } from './utils/anchorPoint.mjs';
 import { rehypePreviewHTML } from './utils/rehypePreviewHTML.mjs';
@@ -29,18 +32,29 @@ export function create(str = '', options = {}) {
     rehypePlugins: [
       rehypeSlug,
       rehypeAutolinkHeadings,
-      [rehypeDocument, {
-        title: `${title ? `${title} & ` : ''} ${subTitle} Quick Reference`,
-        css: [ ...options.css ],
-        link: [
-          {rel: 'icon', href: favicon, type: 'image/svg+xml'}
-        ],
-        meta: [
-          { description: `${description}为开发人员分享快速参考备忘单。` },
-          { keywords: `Quick,Reference,cheatsheet,${!options.isHome && options.filename || ''}` }
-        ]
-      }],
+        [rehypeDocument, {
+          title: `${title ? `${title} & ` : ''} ${subTitle} Quick Reference`,
+          css: [ ...options.css ],
+          link: [
+            {rel: 'icon', href: favicon, type: 'image/svg+xml'}
+          ],
+          meta: [
+            { description: `${description}为开发人员分享快速参考备忘单。` },
+            { keywords: `Quick,Reference,cheatsheet,${!options.isHome && options.filename || ''}` }
+          ]
+        }]
     ],
+    filterPlugins: (type, plugins = []) => {
+      if (type === 'rehype') {
+        const dt = plugins.filter(plug => {
+          return /(rehypeRaw)/.test(plug.name) ? false : true;
+        });
+        // 放在 rehypeDocument 前面
+        dt.unshift(rehypeRaw)
+        return dt;
+      }
+      return plugins
+    },
     rewrite: (node, index, parent) => {
       rehypePreviewHTML(node, parent);
       rehypeTitle(node, options.filename);
@@ -48,11 +62,19 @@ export function create(str = '', options = {}) {
       tooltips(node, index, parent);
       htmlTagAddAttri(node, options);
       rehypeUrls(node);
-      if (node.type === 'element' && node.tagName === 'body') {
-        node.children = getTocsTree([ ...node.children ]);
-        node.children.unshift(header(options));
-        node.children.push(footer());
-        node.children.push(anchorPoint());
+      if (node.children) {
+        if (node.type === 'element' && node.tagName === 'body') {
+          const tocsData = getTocsTree([ ...node.children ]);
+          if (!options.isHome) {
+            const tocsMenus = getTocsTitleNode([...tocsData]);
+            node.children = addTocsInWarp([...tocsData], getTocsTitleNodeWarpper(tocsMenus))
+          } else {
+            node.children = tocsData;
+          }
+          node.children.unshift(header(options));
+          node.children.push(footer());
+          node.children.push(anchorPoint());
+        }
       }
     }
   }
diff --git a/scripts/style.css b/scripts/style.css
index 800ecfa..58b5102 100644
--- a/scripts/style.css
+++ b/scripts/style.css
@@ -66,6 +66,7 @@ body {
   --color-accent-emphasis: #0969da;
   --color-attention-subtle: #fff8c5;
   --color-danger-fg: #cf222e;
+  --box-shadow: 109 109 109;
 }
 
 [data-color-mode*='dark'], [data-color-mode*='dark'] body {
@@ -112,6 +113,7 @@ body {
   --color-accent-emphasis: #1f6feb;
   --color-attention-subtle: rgba(187,128,9,0.15);
   --color-danger-fg: #f85149;
+  --box-shadow: 0 0 0;
 }
 
 body {
@@ -474,6 +476,64 @@ a.text-grey {
   display: flex;
   flex-direction: column;
   gap: 3rem;
+  position: relative;
+}
+.menu-tocs {
+  position: sticky;
+  top: 0;
+  z-index: 88;
+  display: inline-flex;
+}
+.menu-tocs:hover > .menu-modal {
+  display: block;
+  border-radius: 0.5rem;
+  padding: 0.3rem;
+  max-height: 100vh;
+  overflow: auto;
+  background-color: var(--color-canvas-subtle);
+  box-shadow: 0 8px 24px rgba(var(--box-shadow)/0.2);
+}
+.menu-tocs > .menu-btn {
+  border: 1px solid var(--color-border-default);
+  display: flex;
+  border-radius: 0.3rem;
+  padding: 0.3rem 0.4rem;
+  font-size: 1.3rem;
+  margin-left: -3rem;
+  margin-top: 0.3rem;
+  position: absolute;
+}
+.menu-tocs > .menu-modal {
+  width: 260px;
+  position:absolute;
+  display: none;
+  margin-left: -1rem;
+}
+.menu-tocs > .menu-modal a + a {
+  margin-bottom: 0.2rem;
+}
+.menu-tocs > .menu-modal a:hover {
+  background-color: var(--color-neutral-muted);
+}
+.menu-tocs > .menu-modal a.is-active-link {
+  background-color: var(--color-border-muted);
+  text-decoration-color: #10b981;
+}
+.menu-tocs > .menu-modal a {
+  display: block;
+  overflow: hidden;
+  padding: 0.3rem 0.5rem;
+}
+
+.menu-tocs > .menu-modal a.leve2 {
+  font-weight: bold;
+}
+
+.menu-tocs > .menu-modal a.leve3 {
+  padding-left: 1.2rem;
+}
+.menu-tocs > .menu-modal a.leve4, .menu-tocs > .menu-modal a.leve5, .menu-tocs > .menu-modal a.leve6 {
+  padding-left: 2.1rem;
 }
 
 .wrap-header.h2wrap > h2 {
diff --git a/scripts/utils/anchorPoint.mjs b/scripts/utils/anchorPoint.mjs
index f747191..5d67447 100644
--- a/scripts/utils/anchorPoint.mjs
+++ b/scripts/utils/anchorPoint.mjs
@@ -3,6 +3,7 @@ const scripts = `
 if(('onhashchange' in window) && ((typeof document.documentMode==='undefined') || document.documentMode==8)) {
   window.onhashchange = function () {
     anchorPoint()
+    updateAnchor()
   };
 }
 function anchorPoint() {
@@ -16,6 +17,26 @@ function anchorPoint() {
   }
 }
 anchorPoint();
+
+function updateAnchor(element) {
+  const anchorContainer = document.querySelectorAll('.menu-tocs .menu-modal a.tocs-link');
+  anchorContainer.forEach((tocanchor) => {
+    tocanchor.classList.remove('is-active-link');
+  });
+  const anchor = element || document.querySelector(\`a.tocs-link[href='\${decodeURIComponent(window.location.hash)}']\`);
+  console.log('anchor', anchor)
+  if (anchor) {
+    anchor.classList.add('is-active-link');
+  }
+}
+// toc 定位
+updateAnchor()
+const anchor = document.querySelectorAll('.menu-tocs .menu-modal a.tocs-link');
+anchor.forEach((item) => {
+  item.addEventListener('click', (e) => {
+    updateAnchor()
+  })
+})
 `;
 
 export function anchorPoint() {
diff --git a/scripts/utils/getSVGNode.mjs b/scripts/utils/getSVGNode.mjs
index 00e7138..9d6d424 100644
--- a/scripts/utils/getSVGNode.mjs
+++ b/scripts/utils/getSVGNode.mjs
@@ -1,8 +1,11 @@
 import fs from 'fs-extra';
+import path from 'path';
 import rehypeParse from 'rehype-parse';
 import {unified} from 'unified';
 import { VFile } from 'vfile';
 
+export const ICONS_PATH = path.resolve(process.cwd(), 'scripts/assets')
+
 export function getSVGNode(iconPath, space = 'svg') {
   const svgStr = fs.readFileSync(iconPath);
   const processor = unified().use(rehypeParse,{ fragment: true, space })
diff --git a/scripts/utils/getTocsTree.mjs b/scripts/utils/getTocsTree.mjs
index e3698e2..fd44690 100644
--- a/scripts/utils/getTocsTree.mjs
+++ b/scripts/utils/getTocsTree.mjs
@@ -1,5 +1,71 @@
+import path from 'path';
 import { panelAddNumber } from './panelAddNumber.mjs';
 import { getChilds, getHeader } from './childs.mjs';
+import { ICONS_PATH, getSVGNode } from './getSVGNode.mjs';
+
+export const titleNum = (tagName = '') => Number(tagName.replace(/^h/, ''));
+
+export function getTocsTitleNode(arr = [], result = []) {
+  arr.forEach(({ tagName, type, properties, children }) => {
+    if (/^h[23456]/.test(tagName)) {
+      const num = titleNum(tagName)
+      const props = { 'aria-hidden': "true", class: `leve${num} tocs-link`, href: '#' + (properties.id || '') }
+      result.push({ tagName: 'a', type, properties: props, children: (children || []).filter(m => m.type === 'text') })
+    } else if (children?.length > 0) {
+      result = result.concat(getTocsTitleNode(children))
+    }
+  });
+  return result
+}
+
+export function addTocsInWarp(tocsData = [], menuData, isDone = false) {
+  const childs = tocsData.map((item) => {
+    if (item.properties?.class?.includes('h1wrap-body')) {
+      isDone = true;
+    }
+    if (!isDone && item.children) {
+      item.children = addTocsInWarp([...item.children], menuData, isDone)
+    }
+    return item
+  });
+  if (isDone) {
+    childs.splice(1, 0, menuData);
+  }
+  return childs
+}
+
+export const getTocsTitleNodeWarpper = (children = []) => {
+  const iconPath = path.resolve(ICONS_PATH, `menu.svg`);
+  const svgNode = getSVGNode(iconPath);
+  return {
+    type: 'element',
+    tagName: 'div',
+    properties: {
+      class: 'menu-tocs',
+    },
+    children: [
+      {
+        type: 'element',
+        tagName: 'div',
+        properties: {
+          class: 'menu-btn',
+        },
+        children: [
+          // { type: 'text', value: 'menu' }
+          ...svgNode
+        ]
+      },
+      {
+        type: 'element',
+        tagName: 'div',
+        properties: {
+          class: 'menu-modal',
+        },
+        children: children
+      }
+    ]
+  }
+}
 
 /** Markdown 文档转成树形结构 */
 export function getTocsTree(arr = [], result = []) {
@@ -14,9 +80,7 @@ export function getTocsTree(arr = [], result = []) {
     if (level === -1) {
       level = toc.number;
     }
-    const titleNum = Number(toc.tagName?.replace(/^h/, ''));
-
-    if (toc.number === level && titleNum === level) {
+    if (toc.number === level && titleNum(toc.tagName) === level) {
       const header = getHeader(data.slice(n), level);
       const wrapCls = ['wrap'];
       const headerCls = ['wrap-header', `h${level}wrap`];
diff --git a/scripts/utils/homeCardIcons.mjs b/scripts/utils/homeCardIcons.mjs
index 1982c68..2fad267 100644
--- a/scripts/utils/homeCardIcons.mjs
+++ b/scripts/utils/homeCardIcons.mjs
@@ -1,8 +1,6 @@
 import fs from 'fs-extra';
 import path from 'path';
-import { getSVGNode } from './getSVGNode.mjs';
-
-export const ICONS_PATH = path.resolve(process.cwd(), 'scripts/assets')
+import { getSVGNode, ICONS_PATH } from './getSVGNode.mjs';
 
 export function homeCardIcons(node, parent, isHome) {
   if (isHome && node && node.type === 'element' && node.properties?.class?.includes('home-card')) {
diff --git a/scripts/utils/rehypeTitle.mjs b/scripts/utils/rehypeTitle.mjs
index 36b028d..d88a448 100644
--- a/scripts/utils/rehypeTitle.mjs
+++ b/scripts/utils/rehypeTitle.mjs
@@ -1,7 +1,6 @@
 import fs from 'fs-extra';
 import path from 'path';
-import { getSVGNode } from './getSVGNode.mjs';
-import { ICONS_PATH } from './homeCardIcons.mjs';
+import { getSVGNode, ICONS_PATH } from './getSVGNode.mjs';
 
 export function rehypeTitle(node, iconName) {
   if (node.type === 'element' && node.tagName === 'h1' && iconName !== 'index') {