思源笔记可移动的导航大纲:js 代码片段

导航目录大体功能:(使用方法:把代码放进 js 代码片段,粘贴完注意第 8 条)

  1. 随着笔记标签页的切换,导航内容也能相应切换
  2. 目录字体大小可调
  3. 可折叠起来
  4. 导航目录过长,可滚动
  5. 鼠标点击目录,可以导航到正文相应位置
  6. 鼠标悬停在目录上,可弹出浮窗
  7. 鼠标单击块,浮动大纲中对应的标题内容颜色会改变。再次点击会找上一级标题
  8. image.png

看下图,应该能明白。更新时间 20250227,修复了一些 bug

screenshots.gif

// ========== 工具函数 ========== // 使用原生DOMParser解析HTML并提取纯文本内容 const parseHtmlToText = (html) => { return html.replace(/<[^>]+>/g, '').replace(/&nbsp/g, ' '); // 注意,使用时要在&nbsp后面加一个分号; }; // 通用高亮函数,返回是否匹配成功 function highlightOutlineElements(outlineContent, nodeId, textContent) { const outlineElements = outlineContent.querySelectorAll("[data-href]"); let isMatched = false; // 用于标记是否找到匹配项 outlineElements.forEach((element) => { const href = element.getAttribute('data-href'); const hrefId = href.split('/').pop(); const isMatch = nodeId ? hrefId === nodeId : element.textContent.trim() === textContent; // 只在必要时修改样式 if (isMatch && element.style.backgroundColor !== 'green') { element.style.backgroundColor = 'green'; // 高亮背景颜色 isMatched = true; // 标记匹配成功 } else if (!isMatch && element.style.backgroundColor === 'green') { element.style.backgroundColor = ''; // 恢复默认背景颜色 } }); return isMatched; // 返回是否匹配成功 } // ========== 数据获取函数 ========== // 获取文档信息,包括 rootID async function getRootID({ id }) { const response = await fetch(`/api/block/getDocInfo`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ id }), }); const data = await response.json(); return data.data.rootID; // 直接返回 rootID } // 获取文档大纲的函数 const getDocOutline = async (docId) => { try { const response = await fetch(`/api/outline/getDocOutline`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ id: docId }), }); if (!response.ok) { throw new Error(`网络请求失败:${response.status}`); } const data = await response.json(); if (data.code === 0) { return data.data; } else { console.error('获取文档目录结构失败:', data.msg); return null; } } catch (error) { console.error('获取文档目录结构失败:', error.message); return null; } }; // ========== 大纲处理函数 ========== // 收集大纲标题的函数 const collectTitles = (data) => { let titles = []; for (let item of data) { let text = (item.name || item.content).trim(); // 解析HTML为纯文本 const parsedText = parseHtmlToText(text); titles.push({ text, parsedText, id: item.id, depth: item.depth, needParse: text !== parsedText, }); // 递归处理子标题 if (item.count > 0) { titles = titles.concat(collectTitles(item.blocks ?? item.children)); } } return titles; }; // 生成大纲内容的函数 const generateOutline = async (nodeId, outlineContent) => { console.log("开始生成大纲,节点 ID:", nodeId); // 调试日志 try { if (!nodeId) { outlineContent.innerHTML = "<li>未找到有效节点,请点击文档内容。</li>"; return; } // 检查是否需要重新生成大纲 const currentOutlineNodeId = outlineContent.getAttribute('data-current-node-id'); if (currentOutlineNodeId === nodeId) { console.log("大纲已存在,无需重新生成"); // 调试日志 return; } const docOutline = await getDocOutline(nodeId); // 获取文档大纲 if (!docOutline) { outlineContent.innerHTML = "<li>无法获取文档目录结构。</li>"; return; } const titles = collectTitles(docOutline); // 收集大纲标题 const fragment = document.createDocumentFragment(); // 创建文档片段 // 遍历标题并生成列表项 titles.forEach(title => { const listItem = document.createElement("li"); const link = document.createElement("span"); link.setAttribute("data-type", "a"); link.setAttribute("data-href", `siyuan://blocks/${title.id}`); // 使用 textContent 设置内容,避免HTML被解析 link.textContent = title.parsedText; // 设置链接样式 Object.assign(link.style, { color: "#000", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", display: "inline-block", maxWidth: "100%", }); // 添加链接点击事件 link.addEventListener("mousedown", (e) => { if (e.button === 0) { e.preventDefault(); const selection = window.getSelection(); const range = document.createRange(); range.selectNodeContents(link); selection.removeAllRanges(); selection.addRange(range); } }); link.addEventListener('click', function (event) { event.preventDefault(); const href = this.getAttribute("data-href"); window.open(href, '_blank'); }); // 设置列表项的缩进 listItem.style.paddingLeft = `${title.depth * 15}px`; listItem.appendChild(link); fragment.appendChild(listItem); }); // 清空并更新大纲内容 outlineContent.innerHTML = ""; outlineContent.appendChild(fragment); // 更新当前大纲的节点 ID outlineContent.setAttribute('data-current-node-id', nodeId); console.log("大纲生成完成"); // 调试日志 } catch (error) { outlineContent.innerHTML = `<li>生成大纲失败:${error.message}</li>`; } }; // ========== 页面交互函数 ========== // 修改函数:根据 rootId 查找并返回所有兄弟元素的 title 文本数组 function getLastSiblingTitle(rootId) { const allBreadcrumbItems = document.querySelectorAll('.protyle-breadcrumb__item'); for (const item of allBreadcrumbItems) { if (item.getAttribute('data-node-id') === rootId && item.classList.contains('protyle-breadcrumb__item--active')) { const parent = item.parentElement; const siblings = Array.from(parent.children).filter(sibling => sibling !== item); const titles = []; siblings.forEach(sibling => { const titleElement = sibling.querySelector('.protyle-breadcrumb__text'); if (titleElement && titleElement.getAttribute('title')) { titles.push(titleElement.getAttribute('title')); } }); return titles; // 返回包含所有兄弟节点标题的数组 } } return []; // 如果未找到符合条件的元素,返回空数组 } // 处理 NodeHeading 类型 function handleNodeHeading(outlineContent, nodeId) { console.log("处理 NodeHeading 类型,节点 ID:", nodeId); // 调试日志 highlightOutlineElements(outlineContent, nodeId, null); } // 处理非 NodeHeading 类型 function handleNonNodeHeading(outlineContent, textContentArray) { console.log("处理非 NodeHeading 类型,兄弟节点标题数组:", textContentArray); // 调试日志 if (Array.isArray(textContentArray) && textContentArray.length > 0) { // 倒序遍历数组,依次尝试匹配 for (let i = textContentArray.length - 1; i >= 0; i--) { const currentLine = textContentArray[i]; if (highlightOutlineElements(outlineContent, null, currentLine)) { return; // 匹配成功后退出循环 } } } } // 全局点击事件处理函数 const handleClick = async (e, outlineContent) => { console.log("点击事件触发,目标元素:", e.target); // 调试日志 let target = e.target; while (target && target !== document && !target.hasAttribute('data-node-id')) { target = target.parentNode; } if (target && target.hasAttribute('data-node-id')) { const nodeId = target.getAttribute('data-node-id'); try { // 获取 rootID const rootID = await getRootID({ id: nodeId }); if (rootID) { console.log("开始生成大纲,节点 ID:", nodeId); // 调试日志 await generateOutline(nodeId, outlineContent); if (target.getAttribute('data-type') === 'NodeHeading') { handleNodeHeading(outlineContent, nodeId); } else { const siblingTitles = getLastSiblingTitle(rootID); if (siblingTitles.length > 0) { handleNonNodeHeading(outlineContent, siblingTitles); } } } } catch (error) { console.error('获取 rootID 失败:', error.message); } } else { outlineContent.innerHTML = "<li>未找到有效节点,请点击文档内容。</li>"; } }; // ========== UI 创建函数 ========== // 创建大纲面板的函数 const createOutlinePanel = () => { const outlinePanel = document.createElement("div"); Object.assign(outlinePanel.style, { position: "fixed", top: "100px", left: "1000px", width: "200px", height: "30px", background: "#f1f1f1", border: "1px solid #ccc", borderRadius: "5px", padding: "0", boxShadow: "0 0 10px rgba(0, 0, 0, 0.1)", zIndex: "1000", overflow: "hidden", }); const topButtonsContainer = createTopButtonsContainer(); outlinePanel.appendChild(topButtonsContainer); const outlineTitle = document.createElement("h3"); outlineTitle.textContent = "大纲"; Object.assign(outlineTitle.style, { margin: "0 0 10px", }); outlinePanel.appendChild(outlineTitle); const outlineContent = document.createElement("ul"); outlineContent.id = "outline-list"; Object.assign(outlineContent.style, { listStyle: "none", padding: "0", margin: "0", fontSize: "14px", marginTop: "20px", overflowY: "auto", maxHeight: "340px", }); outlineContent.setAttribute("draggable", "false"); outlineContent.addEventListener("dragstart", (e) => e.preventDefault()); outlinePanel.appendChild(outlineContent); const toggleButtonInstance = topButtonsContainer.querySelector('button:nth-child(2)'); toggleButtonInstance.textContent = "展开"; let isExpanded = false; toggleButtonInstance.addEventListener("click", () => { isExpanded = !isExpanded; outlinePanel.style.height = isExpanded ? "400px" : `${topButtonsContainer.offsetHeight}px`; toggleButtonInstance.textContent = isExpanded ? "折叠" : "展开"; }); enableDragging(outlinePanel, topButtonsContainer); return { outlinePanel, outlineContent }; }; // 创建顶部按钮容器的函数 const createTopButtonsContainer = () => { const topButtonsContainer = document.createElement("div"); Object.assign(topButtonsContainer.style, { position: "absolute", top: "0", left: "0", right: "0", height: "20px", backgroundColor: "#f1f1f1", display: "flex", justifyContent: "space-between", alignItems: "center", padding: "5px", }); const showOutlineButton = document.createElement("button"); showOutlineButton.textContent = "思源大纲"; Object.assign(showOutlineButton.style, { padding: "5px", background: "#007bff", color: "#fff", border: "none", borderRadius: "5px", cursor: "pointer", }); const toggleButtonElement = document.createElement("button"); toggleButtonElement.textContent = "展开"; Object.assign(toggleButtonElement.style, { padding: "5px", background: "#ccc", border: "none", borderRadius: "5px", cursor: "pointer", }); topButtonsContainer.appendChild(showOutlineButton); topButtonsContainer.appendChild(toggleButtonElement); return topButtonsContainer; }; // 创建字体大小调整按钮的函数 const createFontButtonsContainer = (outlineContent) => { const fontButtonsContainer = document.createElement("div"); Object.assign(fontButtonsContainer.style, { display: "flex", gap: "5px", }); const decreaseFontSizeButton = document.createElement("button"); decreaseFontSizeButton.textContent = "-"; Object.assign(decreaseFontSizeButton.style, { width: "20px", height: "20px", fontSize: "16px", border: "none", background: "#ccc", borderRadius: "50%", }); decreaseFontSizeButton.addEventListener("click", () => { const currentSize = parseFloat(outlineContent.style.fontSize); outlineContent.style.fontSize = `${Math.max(currentSize - 1, 10)}px`; }); const increaseFontSizeButton = document.createElement("button"); increaseFontSizeButton.textContent = "+"; Object.assign(increaseFontSizeButton.style, { width: "20px", height: "20px", fontSize: "16px", border: "none", background: "#ccc", borderRadius: "50%", }); increaseFontSizeButton.addEventListener("click", () => { const currentSize = parseFloat(outlineContent.style.fontSize); outlineContent.style.fontSize = `${Math.min(currentSize + 1, 24)}px`; }); fontButtonsContainer.appendChild(decreaseFontSizeButton); fontButtonsContainer.appendChild(increaseFontSizeButton); return fontButtonsContainer; }; // 实现面板拖动功能的函数 const enableDragging = (outlinePanel, topButtonsContainer) => { let isDragging = false; let offsetX, offsetY; topButtonsContainer.style.cursor = "move"; topButtonsContainer.addEventListener("mousedown", (e) => { if (isDragging) return; isDragging = true; offsetX = e.clientX - Number(outlinePanel.style.left.replace('px', '')); offsetY = e.clientY - Number(outlinePanel.style.top.replace('px', '')); const onMouseMove = (e) => { if (!isDragging) return; let newX = e.clientX - offsetX; let newY = e.clientY - offsetY; const minX = 20; const minY = 20; const maxX = window.innerWidth - outlinePanel.offsetWidth - 20; const maxY = window.innerHeight - outlinePanel.offsetHeight - 20; newX = Math.max(minX, Math.min(newX, maxX)); newY = Math.max(minY, Math.min(newY, maxY)); outlinePanel.style.left = `${newX}px`; outlinePanel.style.top = `${newY}px`; }; const onMouseUp = () => { isDragging = false; document.removeEventListener("mousemove", onMouseMove); document.removeEventListener("mouseup", onMouseUp); }; document.addEventListener("mousemove", onMouseMove); document.addEventListener("mouseup", onMouseUp); }); }; // ========== 主函数 ========== const main = () => { const { outlinePanel, outlineContent } = createOutlinePanel(); document.body.appendChild(outlinePanel); const fontButtonsContainer = createFontButtonsContainer(outlineContent); const topButtonsContainer = outlinePanel.querySelector('div'); topButtonsContainer.appendChild(fontButtonsContainer); document.addEventListener('click', (e) => handleClick(e, outlineContent)); }; main();
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    25295 引用 • 104414 回帖
2 操作
cxg318 在 2025-02-27 01:25:05 更新了该帖
cxg318 在 2025-02-24 00:11:08 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • Floria233

    这个很棒啊,感谢大大。就我的理解,这个设计是不是和 ob 的 floating index(好像是这个)插件相似?就是可以使大纲悬浮起来——就动图与说明看起来,似乎是这个样子?

    (我就说嘛,ob 能做到的东西,思源大差不差也都能做到类似的,就是这边开发者人手缺乏罢了,扼腕……)

    这个我所能想到的第一个优点就是节省面板位置,因为插件那么多,而软件本体除了编辑器之外的其他部分又那么小,可谓寸土寸金,参考我的话,左边是自带文档树 + 书签两个部件,右边是二级文档树这个部件,这三个是长期固定,常用的浮动面板是 knote 和小记,偶尔需要查看大纲,就得按快捷键切换了(因为不是每个文档都有大纲,需要用的时候才会固定,不用的时候就不希望它占用位置)

    因为文档跳转频繁,文档树与其浮动还是贴边吧,而浮动的大纲面板可以按照需要跳出来,最能辅助正文查看又能灵活调取(不至于总是放在某个地方),唯有它浮动起来是最合适的 😁

    我的体验是,它是一个有则最好,无则稍憾(思源本体可以凑合)而绝非鸡肋的功能设计,ob,flowus(notion 不知道)还有有道云(印象不知道)这种都有特别给出这个设计啊,所以它绝对是有必要的

    目前我所想到的优化方向,1 设计上,应该是这个面板先跟主题风格和谐一致,除此之外,2 这个 UI 的信息界面,大大要不要参考动图右边那个大纲插件设计?给每个大标题旁边都用数字标注其下小标题的数量之类的?

    另,有道云的悬浮大纲,在不用时会变成一道道长短不一的横线,这个看起来很简洁,但可以的话,请大大千万别做成这样,因为我用过几次,每次都需要鼠标浮过去它才会显现,不够直观还增加了操作步骤。

    也不希望完全参照 ob 的那个插件——只能在一个固定位置悬浮(这个当大纲标题太长时,偶尔会和正文重合起来),就是动图中这种自由拖动我感觉挺好的 👍(不过它是只能在编辑区拖动?还是可以在整个界面拖动呢?后者感觉更好一点)

    其实这个面板,只要存在了就是它最大的意义,其他都是锦上添花(来自小白的看法)

    1 回复
  • cxg318
    作者

    思源本体内任意位置拖动的

  • 感觉挺好的工具,有很多场景会需要。

  • zzshang

    鸡肋

  • Floria233

    用不用取决于使用者,开不开发取决于开发者。

    使用者对开发者所做的某个非强制不影响使用体验的功能缺乏感知,就是楼下这种了。

    很多开发者做某个东西,最开始都是基于自己的某些目的,有的是练手,有的是自用,有的是为爱发电,大大感觉有必要就做吧,真正在需要者的使用场景里,还是相当实用滴。

    有句糙话是,我可以不用,你不能没有(捂脸),大概就是这种情况。关键是看大大的动图,已经做到一定可用性了,做好了之后一定会有人需要的。👍

    1 回复
  • cxg318 2 评论
    作者

    再修修,如果大家有一些好的点子,就加上去,到时候成形了,代码放出来

    1 回复
    大大,这些点子感觉可以参考 AI,之前用 joplin 时总觉得文档树很难用,为此还特意去论坛反馈,使用 AI 帮助整理说辞时,AI 给出了更多我都没想到的优化设计方案(乍一看确实也很合理),到了那份上,感觉不是满足使用者需求,而是在考验开发者水平了 😂
    Floria233
    我搜索了一下,给个示例,并非冒犯,只为给大大你参考,要是看不惯 AI 可以忽视。我个人是觉得它里面所给出的某些方向似乎特别难。
    Floria233
  • Floria233

    针对笔记软件中悬浮目录功能的优化方向,可以从以下多个维度进行深入改进,提升用户体验和效率:

    这个是 AI 所写,个人感想使用【】


    一、交互体验优化

    1. 动态折叠与智能展开

      • 层级感知折叠:根据用户当前阅读位置(如标题层级),自动折叠非相关层级目录(如仅展示当前章节的 2-3 级标题)。【这个看动图好像可以做到】
      • 手势交互:支持双指捏合展开/折叠目录层级,长按目录项直接拖拽调整文档结构。【这个涉及到的知识是不是有点难???二级文档树到现在都没法自由拖动排序,可能就是这个原因】
      • 焦点跟随:滚动正文时,悬浮目录自动高亮并居中显示当前章节,同时折叠非相邻章节。【这个感觉比较好用】
    2. 快捷操作集成

      • 右键菜单增强:在目录项右键添加「跳转到子标题」「复制标题链接」「快速拆分/合并章节」等高频操作。【这个在我看来,似乎有点繁琐,不过如果加上好像也挺好用,但这应当是个很大的工作量】
      • 拖拽多选:支持框选或 Shift 多选目录项,批量调整章节顺序或层级(类似文件管理器逻辑)。【这个背后原理不太懂,也许很难???它这个和文档树有点类似,选了目录就直接调动整个文档界面的内容,这个真的有必要吗???这种使用频率似乎不够高……】

    二、视觉与信息呈现优化

    1. 三维视觉反馈

      • 深度指示:通过阴影、缩进层级和颜色渐变区分标题层级(如一级标题深色加粗,次级标题逐渐淡化)。【UI 方面的,这个感觉不错】
      • 阅读进度可视化:在目录项右侧添加细进度条,显示该章节的阅读完成比例(通过文字密度分析估算)。【思源可以联动到这份上吗?估计也不容易】
    2. 动态内容预览

      • Hover 卡片:鼠标悬停目录项时,弹出缩略图或关键句预览,避免频繁跳转。【感觉复杂,悬浮需求有必要吗?如果可以开发出来可能会好用,但可能会影响思源性能,造成卡顿,这是我的揣测】
      • 关联标签:自动标记含图片、表格、代码块的章节,通过图标直观展示内容类型。【同上】

    三、功能增强

    1. 智能目录管理

      • 自动语义重组:通过 NLP 识别内容主题,建议合并/拆分章节(如检测到连续多个短段落讨论同一主题时提示合并)。【复杂】
      • 版本对比:记录目录结构历史版本,支持与早期版本对比并恢复。【这个感觉很没必要,然而这个真是 AI 才能提出来,一般使用者想不到这个】
    2. 跨文档联动

      • 多文档目录聚合:在协同场景下,悬浮目录可同时显示多个关联文档的目录(如项目文档 + 会议纪要),支持跨文档跳转。【这个是啥?有点不懂】
      • 书签同步:将目录项与文档内自定义书签绑定,实现混合导航。【无法想象,从来没有见过哪个目录导航能做到这份上,但不明觉厉】

    四、场景化适配

    1. 创作模式优化

      • 大纲模式融合:进入写作模式时,悬浮目录自动切换为可编辑大纲,支持直接修改标题文本或升降级。【这个感觉不错,不过话说回来,感觉工作量不小】
      • 思维导图联动:点击目录项右侧图标,一键生成以当前章节为中心的局部思维导图。【同上】
    2. 移动端专属设计

      • 摇杆式导航:在窄屏下将目录转换为底部半屏摇杆,滑动控制滚动速度,点击快速定位。【不懂】
      • 语音导航:支持语音指令如「跳转到第三节」「展开所有二级标题」。【感觉这个是真鸡肋】

    五、性能与底层优化

    1. 实时响应机制【这个是给开发者的建议,不说了】

      • 增量加载:超长文档中仅渲染可视区域目录项,滚动时动态加载(类似虚拟列表技术)。
      • 差异更新:通过 Diff 算法仅更新变动的目录节点,避免整体重绘导致的卡顿。
    2. 智能预判

      • 滚动惯性预测:根据滚动速度预加载即将到达的目录节点,确保流畅的高亮切换。

    六、用户自定义体系

    1. 个性化规则引擎
      • 条件过滤:设置「自动隐藏所有空章节」「仅显示含 TODO 标签的节点」等自定义过滤规则。
      • 样式模板库:提供不同场景的目录主题(如学术论文模式、会议记录模式),支持导出分享。

    示例方案:智能写作助手模式

    • 场景:用户撰写技术文档时,悬浮目录右侧常驻 AI 面板:【这个是接入了 AI 的目录,和现在大大做的目录,不是一回事啊,同理,感觉这个不容易做到】
      1. 自动检测「缺少结论段」并红色警示
      2. 推荐插入「代码示例」「流程图」等模块按钮
      3. 实时显示章节字数统计与建议优化点(如「当前段落术语密度过高」)

    通过以上优化,悬浮目录可从被动导航工具升级为主动创作助手,同时兼顾效率型用户的深度需求和新手用户的易用性。建议采用 A/B 测试逐步推进,优先落地高 ROI 功能(如目录搜索、拖拽调整),再迭代智能功能。【这个应该是给开发者的建议,ROI 这种术语都出来了,哈哈哈】

    1 回复
  • att88 2 评论

    我个人可太需要这个了好嘛!之前论坛找了好几次是否有悬浮大纲悬浮文档树,结果都是没有。思源大纲虽说可以四处移动,但是高宽还是受到主页面限制,有时候大纲没几行内容还占了一大片,老按快捷键开关也很麻烦。就很希望能像 ps 那样工具面板都能页面外悬浮,能专注页面本身不被视觉中心外的东西干扰。感谢作者!希望尽快上架

    文档树原来就是可以悬浮的,但悬浮大纲这个是真没有
    Floria233
    请问文档树怎么悬浮?
    att88
  • cxg318 1 评论
    作者

    扔给我这么多,直接整不会了。😂
    ai 确实能帮忙很多,代码基本是 ai 写的,但要修一些小细节,对于我这等代码小白来说,还是很难的。
    可能一个小问题,扔给 kimi,豆包,deepseek,他们几十次都没法给一个满意的结果,
    最后,还得手动进代码查找修改。
    这里也有很大可能是喂给他们的关键词不够准确。
    思源是一个让人折腾停不下来的软件,但要学的东西实在太多了******

    1 操作
    cxg318 在 2025-02-23 00:39:03 更新了该回帖
    不要吓到了,可以做的就去做,不可以做的就去学或者就不做,躺平也没关系,AI 给的方案感觉是作为商业产品开发,方方面面都考虑到了,但 20% 的功能可以满足使用者 80% 的需求,28 定理无处不在,剩下顶多精益求精。😄
    Floria233
  • LitBearPibs

    大佬赶紧上架吧,插件市场怎么搜到,指个路子啊

  • cxg318
    作者

    7.双击段落里的块(包括段落标题),大纲对应的颜色改变

    screenshots.gif

  • cxg318
    作者

    js 代码片段放出,有需要的拿去用,也欢迎修改的更好。
    肯定有一些 bug,先暂时用着吧。😋

    1 回复
  • att88

    js 代码用了好像没起作用?上面 docker 栏中也没找到相应图标,是不是我哪里使用姿势不对

    1 回复
  • cxg318
    作者

    代码片段有一个是 css,一个是 js,不要填错了

    1 回复
  • att88

    确实填的是 js。代码中有一段 // 解码HTML实体的函数 我这边报错,应该是大大代码块粘贴的时候 html 直接给解析了。改回去后我现在运行正常。感谢!!

    image.png

    1 回复
  • cxg318
    作者

    确实,粘贴时自动被系统解析了。只能粘贴完代码,手动改一下了。因为这是发贴的系统自动改的。

  • NieJianYing via macOS

    丸辣,手机伺服用不了,会从网页跳到桌面程序

  • cxg318
    作者

    更新 20250227

  • mark-j

    能像少数派网页端的 toc 一样就好了

    1 回复
  • cxg318
    作者

    可以用人工智能加工一下,基础已经做好了,改一下也简单的。

请输入回帖内容 ...

推荐标签 标签

  • 钉钉

    钉钉,专为中国企业打造的免费沟通协同多端平台, 阿里巴巴出品。

    15 引用 • 67 回帖 • 281 关注
  • 架构

    我们平时所说的“架构”主要是指软件架构,这是有关软件整体结构与组件的抽象描述,用于指导软件系统各个方面的设计。另外还有“业务架构”、“网络架构”、“硬件架构”等细分领域。

    143 引用 • 442 回帖 • 2 关注
  • Sym

    Sym 是一款用 Java 实现的现代化社区(论坛/BBS/社交网络/博客)系统平台。

    下一代的社区系统,为未来而构建

    524 引用 • 4601 回帖 • 705 关注
  • TextBundle

    TextBundle 文件格式旨在应用程序之间交换 Markdown 或 Fountain 之类的纯文本文件时,提供更无缝的用户体验。

    1 引用 • 2 回帖 • 81 关注
  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 564 关注
  • API

    应用程序编程接口(Application Programming Interface)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

    79 引用 • 431 回帖
  • 阿里巴巴

    阿里巴巴网络技术有限公司(简称:阿里巴巴集团)是以曾担任英语教师的马云为首的 18 人,于 1999 年在中国杭州创立,他们相信互联网能够创造公平的竞争环境,让小企业通过创新与科技扩展业务,并在参与国内或全球市场竞争时处于更有利的位置。

    43 引用 • 221 回帖 • 66 关注
  • PHP

    PHP(Hypertext Preprocessor)是一种开源脚本语言。语法吸收了 C 语言、 Java 和 Perl 的特点,主要适用于 Web 开发领域,据说是世界上最好的编程语言。

    180 引用 • 408 回帖 • 487 关注
  • ReactiveX

    ReactiveX 是一个专注于异步编程与控制可观察数据(或者事件)流的 API。它组合了观察者模式,迭代器模式和函数式编程的优秀思想。

    1 引用 • 2 回帖 • 181 关注
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    83 引用 • 37 回帖
  • 开源

    Open Source, Open Mind, Open Sight, Open Future!

    411 引用 • 3588 回帖
  • Sillot

    Insights(注意当前设置 master 为默认分支)

    汐洛彖夲肜矩阵(Sillot T☳Converbenk Matrix),致力于服务智慧新彖乄,具有彖乄驱动、极致优雅、开发者友好的特点。其中汐洛绞架(Sillot-Gibbet)基于自思源笔记(siyuan-note),前身是思源笔记汐洛版(更早是思源笔记汐洛分支),是智慧新录乄终端(多端融合,移动端优先)。

    主仓库地址:Hi-Windom/Sillot

    文档地址:sillot.db.sc.cn

    注意事项:

    1. ⚠️ 汐洛仍在早期开发阶段,尚不稳定
    2. ⚠️ 汐洛并非面向普通用户设计,使用前请了解风险
    3. ⚠️ 汐洛绞架基于思源笔记,开发者尽最大努力与思源笔记保持兼容,但无法实现 100% 兼容
    29 引用 • 25 回帖 • 117 关注
  • 游戏

    沉迷游戏伤身,强撸灰飞烟灭。

    181 引用 • 821 回帖
  • Telegram

    Telegram 是一个非盈利性、基于云端的即时消息服务。它提供了支持各大操作系统平台的开源的客户端,也提供了很多强大的 APIs 给开发者创建自己的客户端和机器人。

    5 引用 • 35 回帖 • 1 关注
  • Log4j

    Log4j 是 Apache 开源的一款使用广泛的 Java 日志组件。

    20 引用 • 18 回帖 • 29 关注
  • TensorFlow

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

    20 引用 • 19 回帖 • 1 关注
  • iOS

    iOS 是由苹果公司开发的移动操作系统,最早于 2007 年 1 月 9 日的 Macworld 大会上公布这个系统,最初是设计给 iPhone 使用的,后来陆续套用到 iPod touch、iPad 以及 Apple TV 等产品上。iOS 与苹果的 Mac OS X 操作系统一样,属于类 Unix 的商业操作系统。

    89 引用 • 150 回帖
  • BND

    BND(Baidu Netdisk Downloader)是一款图形界面的百度网盘不限速下载器,支持 Windows、Linux 和 Mac,详细介绍请看这里

    107 引用 • 1281 回帖 • 33 关注
  • IBM

    IBM(国际商业机器公司)或万国商业机器公司,简称 IBM(International Business Machines Corporation),总公司在纽约州阿蒙克市。1911 年托马斯·沃森创立于美国,是全球最大的信息技术和业务解决方案公司,拥有全球雇员 30 多万人,业务遍及 160 多个国家和地区。

    17 引用 • 53 回帖 • 144 关注
  • 周末

    星期六到星期天晚,实行五天工作制后,指每周的最后两天。再过几年可能就是三天了。

    14 引用 • 297 回帖
  • 反馈

    Communication channel for makers and users.

    122 引用 • 910 回帖 • 272 关注
  • 又拍云

    又拍云是国内领先的 CDN 服务提供商,国家工信部认证通过的“可信云”,乌云众测平台认证的“安全云”,为移动时代的创业者提供新一代的 CDN 加速服务。

    20 引用 • 37 回帖 • 573 关注
  • Openfire

    Openfire 是开源的、基于可拓展通讯和表示协议 (XMPP)、采用 Java 编程语言开发的实时协作服务器。Openfire 的效率很高,单台服务器可支持上万并发用户。

    6 引用 • 7 回帖 • 104 关注
  • OpenStack

    OpenStack 是一个云操作系统,通过数据中心可控制大型的计算、存储、网络等资源池。所有的管理通过前端界面管理员就可以完成,同样也可以通过 Web 接口让最终用户部署资源。

    10 引用 • 7 关注
  • etcd

    etcd 是一个分布式、高可用的 key-value 数据存储,专门用于在分布式系统中保存关键数据。

    6 引用 • 26 回帖 • 544 关注
  • sts
    2 引用 • 2 回帖 • 227 关注
  • React

    React 是 Facebook 开源的一个用于构建 UI 的 JavaScript 库。

    192 引用 • 291 回帖 • 380 关注