diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 3833078c9a0a1f931410fc84fb04f809109db0d3..ef42263432d06cd01f03e5288aff8ab5144b12e4 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -91,8 +91,6 @@ export default { const id = tokens[idx].attrs?.[aIndex]?.[1]; const tag = tokens[idx].tag; const render = self.renderToken(tokens, idx, options); - - // 自定义标题的 HTML 结构 return `${render}${tag === 'h1' || tag === 'h2' ? `` : ''}`; }; @@ -100,12 +98,11 @@ export default { const tag = tokens[idx].tag; return `${tag === 'h1' || tag === 'h2' ? '' : ''}${self.renderToken(tokens, idx, options)}`; }; - + // 图片 const imageRender = md.renderer.rules.image; md.renderer.rules.image = (...args) => { - const el = `${imageRender!!(...args)}`; - return el; + return `${imageRender!!(...args)}`; }; }, }, diff --git a/docs/.vitepress/src/assets/style/markdown.scss b/docs/.vitepress/src/assets/style/markdown.scss index 45eb21f9d7256c05ad4fb60ad819714566d3a190..ff043337792c167a7f99178135aecbd5ba4547a0 100644 --- a/docs/.vitepress/src/assets/style/markdown.scss +++ b/docs/.vitepress/src/assets/style/markdown.scss @@ -326,7 +326,7 @@ } div.mermaid { - svg[aria-roledescription="error"] { + svg[aria-roledescription='error'] { display: none; } } @@ -338,78 +338,6 @@ } } } - - .img-expand { - width: auto; - max-width: min(936px, 100%); - position: relative; - display: inline-block; - padding: var(--o-gap-2); - margin-left: -8px; - cursor: pointer; - .img-expand-btn { - position: absolute; - width: 32px; - height: 32px; - background-color: rgba(var(--o-black), 0.4); - border: 1px solid rgba(var(--o-black), 0.1); - border-radius: var(--o-radius-xs); - opacity: 0; - z-index: 1; - top: 20px; - right: 20px; - transition: all var(--o-duration-m1) var(--o-easing-standard-in); - &::after { - content: ''; - position: absolute; - top: 3px; - left: 3px; - width: 24px; - height: 24px; - background-color: transparent; - background-image: url('@/assets/category/docs/icon-full-screen.svg'); - background-position: center; - background-size: 24px; - background-repeat: no-repeat; - } - } - - .img-mask { - position: absolute; - top: 8px; - left: 8px; - width: calc(100% - 16px); - height: calc(100% - 16px); - background-color: rgba(var(--o-black), 0.2); - border: 1px solid rgba(var(--o-black), 0.1); - opacity: 0; - border-radius: var(--o-radius-xs); - z-index: 2; - transition: all var(--o-duration-m1) var(--o-easing-standard-in); - } - - @include hover { - .img-expand-btn, - .img-mask { - opacity: 1; - } - } - - @include respond-to('phone') { - max-width: 100%; - .img-expand-btn, - .img-mask { - display: none; - } - } - } - - .img-expand-not { - .img-expand-btn, - .img-mask { - display: none; - } - } } @include in-dark { diff --git a/docs/.vitepress/src/components/FloatingButton.vue b/docs/.vitepress/src/components/FloatingButton.vue index 35fdce8a6e4422694c0f73dfca6dabfafc058bac..53b4b1097181586d9c00682d5f66630feae47fd0 100644 --- a/docs/.vitepress/src/components/FloatingButton.vue +++ b/docs/.vitepress/src/components/FloatingButton.vue @@ -2,7 +2,7 @@ import { ref, computed, onMounted, onUnmounted } from 'vue'; import { OIcon } from '@opensig/opendesign'; -import DocBugDialog from '@/components/DocBugDialog.vue'; +import DocBugDialog from '@/components/doc/DocBugDialog.vue'; import FloatingButtonHome from '@/components/feedback/FloatingButtonHome.vue'; import IconTop from '~icons/app/icon-top.svg'; diff --git a/docs/.vitepress/src/components/GiteeViewSource.vue b/docs/.vitepress/src/components/GiteeViewSource.vue index 34fb77b4a51bd5825d5c549a9bb57acb1e22e759..e262d04b91368f9be7e9a8a84a618fb337e5347d 100644 --- a/docs/.vitepress/src/components/GiteeViewSource.vue +++ b/docs/.vitepress/src/components/GiteeViewSource.vue @@ -56,7 +56,7 @@ const insertGiteeBtn = () => { `; const parser = new DOMParser(); - const svgDoc = parser.parseFromString(svgString, "image/svg+xml"); + const svgDoc = parser.parseFromString(svgString, 'image/svg+xml'); a.appendChild(svgDoc.documentElement); container.appendChild(a); titleDom.nextSibling.parentNode?.insertBefore(container, titleDom.nextSibling); @@ -83,6 +83,27 @@ watch(isPhone, () => { + + diff --git a/docs/.vitepress/src/components/DocBugDialog.vue b/docs/.vitepress/src/components/doc/DocBugDialog.vue similarity index 100% rename from docs/.vitepress/src/components/DocBugDialog.vue rename to docs/.vitepress/src/components/doc/DocBugDialog.vue diff --git a/docs/.vitepress/src/components/AppFooter2.vue b/docs/.vitepress/src/components/doc/DocFooter.vue similarity index 99% rename from docs/.vitepress/src/components/AppFooter2.vue rename to docs/.vitepress/src/components/doc/DocFooter.vue index 546aff7daa7d85385408ab01ae7bfdc091a708a1..b8649d99c0c5adf1831a72bf92cc8b8fc5b5c5b4 100644 --- a/docs/.vitepress/src/components/AppFooter2.vue +++ b/docs/.vitepress/src/components/doc/DocFooter.vue @@ -19,8 +19,6 @@ defineProps({ const baseUrl = 'https://www.openeuler.org'; const { t } = useLocale(); - -linksData2; @@ -703,30 +468,6 @@ const closeZoomBtn = () => { --layout-doc-width: min(1200px, calc(var(--vw100) - var(--layout-doc-menu-offset-left) * 2)); } } - -.feedback-bug-popover { - --popup-bg-color: var(--o-color-fill2); - --popup-radius: var(--o-radius-xs); -} - -.article-detail-container { - margin-top: var(--o-gap-2); - margin-bottom: var(--o-gap-6); - - .gitee { - display: flex; - align-items: center; - color: var(--o-color-link1); - text-decoration: none !important; - - svg { - color: var(--o-color-link1); - width: 16px; - height: 16px; - margin-left: 4px; - } - } -} diff --git a/docs/.vitepress/src/stores/menu.ts b/docs/.vitepress/src/stores/menu.ts deleted file mode 100644 index 66223d71f6f8a4e4a979bff008e6f83355840950..0000000000000000000000000000000000000000 --- a/docs/.vitepress/src/stores/menu.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { computed, onMounted, ref, watch } from 'vue'; -import { defineStore } from 'pinia'; -import { MENU_CONFIG } from '@/config/menu'; -import { DocMenuTree, type DocMenuNodeT } from '@/utils/tree'; -import { useData } from 'vitepress'; - -export const useMenuStore = defineStore('menu', () => { - const rootTree = new DocMenuTree(MENU_CONFIG); - const allNodes = rootTree.root.children; - const { hash, page } = useData(); - - // -------------------- 当前菜单节点 -------------------- - const currentNode = computed(() => { - const href = `/${page.value.filePath.replace('.md', '.html')}`; - - // 是否为hash节点 - if (hash.value) { - const hashHref = `/${page.value.filePath.replace('.md', '.html')}${decodeURIComponent(hash.value)}`; - const hashNode = rootTree.getNodeByHref(rootTree.root, hashHref); - if (hashNode) { - return hashNode; - } - } - - return rootTree.getNodeByHref(rootTree.root, href); - }); - - // -------------------- 当前菜单节点的所有前驱节点 -------------------- - const prevNodes = computed(() => { - return currentNode.value ? rootTree.getPrevNodes(currentNode.value, 1) : []; - }); - - // -------------------- 当前菜单节点的手册节点 -------------------- - const bookNode = computed(() => { - if (!currentNode.value) { - return null; - } - - let node: DocMenuNodeT | null = currentNode.value; - while (node && !node.ismanual) { - node = node.parent; - } - - return node; - }); - - const bookNodes = computed(() => (bookNode.value ? [bookNode.value] : [])); - - // -------------------- 菜单绑定值 -------------------- - const menuValue = ref(''); - const menuExpanded = ref([]); - - const updateExpanded = () => { - const node = rootTree.getNodeByHref(rootTree.root, menuValue.value); - if (!node) { - menuExpanded.value = []; - return; - } - - const arr = rootTree.getPrevNodes(node, 1); - if (node.children?.length > 0) { - arr.push(node); - } - - menuExpanded.value = arr.map((item) => item.id); - }; - - onMounted(() => { - menuValue.value = currentNode.value?.id || ''; - }); - - watch(currentNode, () => { - menuValue.value = currentNode.value?.id || ''; - }); - - watch(menuValue, () => { - updateExpanded(); - }); - - return { - menuValue, // 绑定菜单值 - menuExpanded, // 展开值 - rootTree, // 根节点 - allNodes, // 所有节点 - bookNode, // 手册节点 - bookNodes, // 手册节点数组 - currentNode, // 当前节点 - prevNodes, // 当前节点的所有前驱节点 - }; -}); diff --git a/docs/.vitepress/src/stores/node.ts b/docs/.vitepress/src/stores/node.ts new file mode 100644 index 0000000000000000000000000000000000000000..d3af6408420338766bf8cfd1672faa46c994e3e2 --- /dev/null +++ b/docs/.vitepress/src/stores/node.ts @@ -0,0 +1,61 @@ +import { computed } from 'vue'; +import { defineStore } from 'pinia'; +import { MENU_CONFIG } from '@/config/menu'; +import { DocMenuTree, type DocMenuNodeT } from '@/utils/tree'; +import { useData } from 'vitepress'; + +export const useNodeStore = defineStore('node', () => { + const rootTree = new DocMenuTree(MENU_CONFIG); + const { hash, page } = useData(); + + // 页面路径 + const pathname = computed(() => { + return `/${page.value.filePath.replace('.md', '.html')}`; + }); + const href = computed(() => { + return `${pathname.value}${decodeURIComponent(hash.value)}`; + }); + + // 页面节点 + const pageNode = computed(() => { + return rootTree.getNode(rootTree.root, 'href', pathname.value); + }); + + // 当前节点 + const currentNode = computed(() => { + return hash.value ? rootTree.getNode(rootTree.root, 'href', href.value) || pageNode.value : pageNode.value; + }); + + // 手册节点 + const manualNode = computed(() => { + let node: DocMenuNodeT | null = pageNode.value; + while (node && !node.ismanual) { + node = node.parent; + } + + return node; + }); + + // 模块节点 + const moduleNode = computed(() => { + const node = rootTree.root.children.find((item) => item.href && pathname.value.includes(item.href.replace('index.html', ''))); + if (node && pathname.value.toLocaleLowerCase().includes('/tools/')) { + return node.children.find((item) => item.href && pathname.value.includes(item.href.replace('index.html', ''))); + } + + return node; + }); + + // 所有前驱节点 + const prevNodes = computed(() => { + return currentNode.value ? rootTree.getPrevNodes(currentNode.value, 1) : []; + }); + + return { + currentNode, // 当前节点 + pageNode, // 页面节点 + manualNode, // 手册节点 + moduleNode, // 模块节点 + prevNodes, // 所有前驱节点 + }; +}); diff --git a/docs/.vitepress/src/utils/tree.ts b/docs/.vitepress/src/utils/tree.ts index 41de70955876890d9b055b4d056da81cedecc634..f0c0e8be442799de3c9680cee630be127c2742d0 100644 --- a/docs/.vitepress/src/utils/tree.ts +++ b/docs/.vitepress/src/utils/tree.ts @@ -60,95 +60,26 @@ export class DocMenuTree { } /** - * BFS 广度优先查找节点 + * BFS 广度优先查找第一个符合的节点 * @param {DocMenuNodeT} node 父节点 - * @param {string} val id值 - * @returns {(DocMenuNodeT|undefined)} 查找到节点则返回该节点,未找到返回undefined + * @param {string} key key + * @param {string} val value + * @returns {(DocMenuNodeT|null)} 查找到节点则返回该节点,未找到返回 null */ - getNode(node: DocMenuNodeT, val: string): DocMenuNodeT | undefined { - if (node.href === val) { + getNode(node: DocMenuNodeT, key: keyof DocMenuNodeT, val: any): DocMenuNodeT | null { + if (node[key] === val) { return node; } const children: Array = node.children; for (let i = 0, len = children.length; i < len; i++) { - const rlt = this.getNode(children[i], val); + const rlt = this.getNode(children[i], key, val); if (rlt) { return rlt; } } - } - - /** - * BFS 广度优先查找节点 - * @param {DocMenuNodeT} node 父节点 - * @param {string} val href值 - * @returns {(DocMenuNodeT|undefined)} 查找到节点则返回该节点,未找到返回undefined - */ - getNodeByHref(node: DocMenuNodeT, val: string): DocMenuNodeT | undefined { - if (node.href === val) { - return node; - } - - const children: Array = node.children; - for (let i = 0, len = children.length; i < len; i++) { - const rlt = this.getNodeByHref(children[i], val); - if (rlt) { - return rlt; - } - } - } - - /** - * BFS 广度优先查找节点 - * @param {DocMenuNodeT} node 父节点 - * @param {string} val label - * @returns {(DocMenuNodeT|undefined)} 查找到节点则返回该节点,未找到返回undefined - */ - getNodeByLabel(node: DocMenuNodeT, val: string): DocMenuNodeT | undefined { - if (node.label === val) { - return node; - } - - const children: Array = node.children; - for (let i = 0, len = children.length; i < len; i++) { - const rlt = this.getNodeByLabel(children[i], val); - if (rlt) { - return rlt; - } - } - } - - /** - * 获取菜单首条点击节点 - * @param {DocMenuNodeT} node 父节点 - * @returns {string} 返回节点id - */ - getFirstHrefNode(node: DocMenuNodeT) { - return node.children[0].children[0].id; - } - - /** - * 获取节点-指定深度的前驱节点 - * @param {DocMenuNodeT} node 节点 - * @param {number} targetDepth 目标深度 - * @returns {DocMenuNodeT} 返回前驱节点 - */ - getPrevNode(node: DocMenuNodeT, targetDepth = 0) { - if (targetDepth < 0 || node.depth < targetDepth) { - return undefined; - } - let prev = node.parent; - while (prev) { - if (prev.depth === targetDepth) { - return prev; - } - - prev = prev.parent; - } - - return undefined; + return null; } /** @@ -172,3 +103,18 @@ export class DocMenuTree { return nodes; } } + +export function getNodeHrefSafely(node: DocMenuNodeT): string { + if (node.href && node.href.includes('.html')) { + return node.href; + } + + for (const child of node.children) { + const href = getNodeHrefSafely(child); + if (href) { + return href; + } + } + + return ''; +} diff --git a/docs/.vitepress/src/views/docsNode/TheDocsNode.vue b/docs/.vitepress/src/views/docsNode/TheDocsNode.vue index de9bd08c4102b4dd5bc805118a4e1cef3eb50afc..72d0eccfbb29670932918142d888ea7423558bcb 100644 --- a/docs/.vitepress/src/views/docsNode/TheDocsNode.vue +++ b/docs/.vitepress/src/views/docsNode/TheDocsNode.vue @@ -2,7 +2,7 @@ import { computed, ref, onMounted, onUnmounted } from 'vue'; import { ORow, OCol, OLink } from '@opensig/opendesign'; -import type { DocMenuNodeT } from '@/utils/tree'; +import { getNodeHrefSafely, type DocMenuNodeT } from '@/utils/tree'; import { type PropType } from 'vue'; import { useScreen } from '@/composables/useScreen'; @@ -36,23 +36,6 @@ const nodeMenu = computed(() => { return props.node || []; }); -const getSafeHref = (item: DocMenuNodeT): string => { - // 存在对应的 md 文件 - if (!item?.children?.length) { - return item.href?.split('#')[0] as string; - } - - // 查找子节点 - for (const child of item.children) { - const href = getSafeHref(child); - if (href) { - return href; - } - } - - return ''; -}; - const oscrollerDom = ref(); const menuScrollDom = ref(); @@ -92,7 +75,7 @@ onUnmounted(() => {
- {{ ch.label }} + {{ ch.label }}

{{ ch?.description }}

@@ -100,7 +83,7 @@ onUnmounted(() => { @@ -108,7 +91,7 @@ onUnmounted(() => {
- {{ item.label }} + {{ item.label }}

{{ item?.description }}

diff --git a/docs/.vitepress/src/views/search/TheSearchResult.vue b/docs/.vitepress/src/views/search/TheSearchResult.vue index a500a9e435d30316097ca80c5b420e38759ba7d9..13fe65c73da26cac57b9b118333163a40fec5d47 100644 --- a/docs/.vitepress/src/views/search/TheSearchResult.vue +++ b/docs/.vitepress/src/views/search/TheSearchResult.vue @@ -19,7 +19,6 @@ import { useLocale } from '@/composables/useLocale'; import { useSearchingStore } from '@/stores/common'; import { scrollToTop } from '@/utils/common'; - const route = useRoute(); const { t, locale } = useLocale(); const searchStore = useSearchingStore(); @@ -103,7 +102,7 @@ const searchResult = async () => { let pathTempData = []; - let node = tree.value.getNodeByHref(tree.value.root, activeVal); + let node = tree.value.getNode(tree.value.root, 'href', activeVal); if (node) { while (node && node.depth !== 0 && node.parent) { diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts index a89af7a20159407c49153b181d8fb016bdfaf2ed..e13d9dea574270fd0316fb61f75b85dc68d73a82 100644 --- a/docs/.vitepress/theme/index.ts +++ b/docs/.vitepress/theme/index.ts @@ -17,6 +17,7 @@ import '@/assets/style/element-plus/index.scss'; import VueDOMPurifyHTML from 'vue-dompurify-html'; import MarkdownTitle from '@/components/markdown/MarkdownTitle.vue'; +import MarkdownImage from '@/components/markdown/MarkdownImage.vue'; export default { Layout, @@ -34,5 +35,6 @@ export default { }); // 注册组件 app.component('MarkdownTitle', MarkdownTitle); + app.component('MarkdownImage', MarkdownImage); }, }; diff --git a/scripts/build.js b/scripts/build.js index 9f128be1757ed9fce6539e1fec4f97de18f0c9fa..b5ac0294c76fd987f013efba5d859fd9846fa494 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -267,15 +267,19 @@ async function mergeReferences(filePath) { const currenDirName = path.dirname(filePath); + // 处理当前文件的 href 字段 if (frontmatter.href) { - // 处理当前文件的 href 字段 frontmatter.href = frontmatter.href.startsWith('http') ? frontmatter.href : parseHref(path.resolve(currenDirName, frontmatter.href), frontmatter.label || ''); frontmatter.type = 'page'; } else if (fs.existsSync(path.join(currenDirName, 'index.md'))) { - frontmatter.href = parseHref(path.join(currenDirName, 'index.md'), frontmatter.label || ''); - frontmatter.type = 'page'; + const indexContent = fs.readFileSync(path.join(currenDirName, 'index.md'), 'utf-8'); + const { data } = matter(indexContent); + if (data.overview) { + frontmatter.href = parseHref(path.join(currenDirName, 'index.md'), frontmatter.label || ''); + frontmatter.type = 'page'; + } } else { frontmatter.href = parseHref(currenDirName, frontmatter.label || ''); frontmatter.type = 'path'; @@ -318,7 +322,7 @@ overview: true fs.outputFileSync(path.join(targetPath, item, 'index.md'), indexMdContent.replace('title', `title: ${frontmatter.label}`)); } }); - } catch(err) { + } catch (err) { errors.push({ file: targetPath.replace(__dirname, '').replace(/\\/g, '/'), error: '构建异常 (Build Exception: createOverviewIndexMd)',