Spaces:
Running
Running
stouchinglhh
Claude
sync processor from GitLab c697b6e: 版本 1.19.4 / 前端 1.12.4 —— 服务端 i18n(首屏不再闪英文)、推理模块并入模型页、前端抽出 shared/、缓存键改用前端号
bb59211 Download processor/web/static/js/shared/dom.js from Stouching-Robotics/DataFlowing: direct link, hf CLI and curl.
- Browser
- Download file 2.71 kB
-
https://huggingface.co/spaces/Stouching-Robotics/DataFlowing/resolve/main/processor/web/static/js/shared/dom.js
- Command line
-
hf download hf://spaces/Stouching-Robotics/DataFlowing/processor/web/static/js/shared/dom.js
-
curl -L -o dom.js https://huggingface.co/spaces/Stouching-Robotics/DataFlowing/resolve/main/processor/web/static/js/shared/dom.js
2.71 kB
| /** 极小的 DOM 构造 helper —— 一律 createElement + textContent。 | |
| * | |
| * 为什么不用 innerHTML 拼字符串:checkpoint 的文件名、路径、后端错误信息都 | |
| * 来自磁盘和网络,拼进 HTML 就是一个转义面。仓库里 `escHtml()` 已经有**四份 | |
| * 实现**,其中 dashboard.js 那份还漏了 `String()` 转换 —— 与其再加第五份, | |
| * 不如让新代码从根上不产生转义需求。 | |
| * | |
| * 用法: | |
| * el('div', { class: 'p-2', text: 'hi' }, [el('span', { text: 'x' })]) | |
| */ | |
| const ATTR_ALIASES = { class: 'class', for: 'for', style: 'style' }; | |
| /** 必须走 setAttribute 的键(即使不含连字符)。 | |
| * | |
| * `icon` 是给 `<iconify-icon>` 这个**自定义元素**用的:它只监听 attribute | |
| * 变化。`node.icon = '...'` 只是给元素挂了个 JS 属性,不反映成 attribute, | |
| * 结果就是图标位置一片空白 —— 而且不报错,很难查。 */ | |
| const SET_ATTR = new Set(['icon']); | |
| /** | |
| * @param {string} tag | |
| * @param {object} [attrs] `text` 走 textContent;`on` 是 {事件名: 处理函数}; | |
| * `dataset` 是 {键: 值};其余按属性 setAttribute。 | |
| * @param {Array} [children] 子节点(字符串会被转成文本节点) | |
| */ | |
| export function el(tag, attrs = {}, children = []) { | |
| const node = document.createElement(tag); | |
| for (const [key, value] of Object.entries(attrs)) { | |
| if (value === undefined || value === null || value === false) continue; | |
| if (key === 'text') { | |
| node.textContent = String(value); | |
| } else if (key === 'on') { | |
| for (const [event, handler] of Object.entries(value)) { | |
| node.addEventListener(event, handler); | |
| } | |
| } else if (key === 'dataset') { | |
| for (const [k, v] of Object.entries(value)) node.dataset[k] = String(v); | |
| } else if (ATTR_ALIASES[key] || SET_ATTR.has(key) || key.includes('-')) { | |
| node.setAttribute(key, String(value)); | |
| } else { | |
| node[key] = value; | |
| } | |
| } | |
| append(node, children); | |
| return node; | |
| } | |
| /** 把 children(数组或单值)追加进 node。null/undefined/false 会被跳过, | |
| * 这样 `cond && el(...)` 这种写法可以直接塞进数组。 */ | |
| export function append(node, children) { | |
| const list = Array.isArray(children) ? children : [children]; | |
| for (const child of list) { | |
| if (child === null || child === undefined || child === false) continue; | |
| node.appendChild( | |
| child instanceof Node ? child : document.createTextNode(String(child)), | |
| ); | |
| } | |
| return node; | |
| } | |
| /** 清空一个容器 —— 比 `innerHTML = ''` 明确,也不会触发 HTML 解析。 */ | |
| export function clear(node) { | |
| while (node.firstChild) node.removeChild(node.firstChild); | |
| return node; | |
| } | |