// 已内联于 <script> 中,因此服务器渲染的文本在 hydration 之前即受保护。
(() => {
const root = document.documentElement;
const selector = '[data-font-text]';
const imageSelector = '[data-font-image]';
const pendingSelector = '[data-font-text]:not([data-font-ready]), [data-font-image]:not([data-image-ready])';
const maxWait = 1500;
let currentPath = null;
let cleanup = () => {};
const isHome = (path) => /^\/(?:zh\/?)?(?:index(?:\.html)?)?$/.test(path);
const familyName = (name) => name.trim().replace(/^["']|["']$/g, '');
function stop() {
cleanup();
currentPath = null;
root.classList.remove('home-fonts-loading');
}
function start() {
const path = window.location.pathname;
if (!isHome(path) || !document.fonts) {
stop();
return;
}
if (currentPath === path) return;
stop();
currentPath = path;
let active = true;
let pending = 0;
let sawText = false;
const seen = new Set();
const requests = new Map();
const busy = new Map();
const imageListeners = new Set();
const blockedInteractions = new Set();
const ranges = new Map();
function syncInteractions() {
for (const element of document.querySelectorAll('[data-font-interactive]')) {
if (element.matches(pendingSelector) || element.querySelector(pendingSelector)) {
// 原生 inert 属性同时会阻止键盘聚焦与激活。保留组件自身已有的 inert 状态。
if (!element.inert) {
element.inert = true;
blockedInteractions.add(element);
}
} else if (blockedInteractions.delete(element)) {
element.inert = false;
}
}
}
function finish() {
if (!active) return;
active = false;
root.classList.remove('home-fonts-loading');
clearTimeout(timer);
observer.disconnect();
document.removeEventListener('DOMContentLoaded', scan);
for (const [element, readyKey] of busy) {
element.dataset[readyKey] = 'fallback';
element.removeAttribute('aria-busy');
}
for (const dispose of imageListeners) dispose();
for (const element of blockedInteractions) element.inert = false;
blockedInteractions.clear();
imageListeners.clear();
busy.clear();
}
function fontRanges() {
// 在样式表就绪后调用;保留实际的 CSS unicode 范围。
if (ranges.size) return;
for (const face of document.fonts) {
const family = familyName(face.family);
const list = ranges.get(family) || [];
for (const part of face.unicodeRange.split(',')) {
const range = part.trim().replace(/^U\+/i, '').split('-');
const lower = parseInt(range[0].replace(/\?/g, '0'), 16);
const upper = parseInt((range[1] || range[0]).replace(/\?/g, 'F'), 16);
list.push([lower, upper]);
}
ranges.set(family, list);
}
}
function requiredFonts(element) {
const samples = new Map();
const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT);
while (walker.nextNode()) {
const node = walker.currentNode;
if (!node.textContent.trim()) continue;
const style = getComputedStyle(node.parentElement);
const families = style.fontFamily.split(',').map(familyName);
for (const character of node.textContent) {
const point = character.codePointAt(0);
const family = families.find((name) => (ranges.get(name) || []).some(([a, b]) => a [spec, [...chars].join('')]);
}
function scan() {
if (!active) return;
if (document.readyState === 'loading') {
syncInteractions();
return;
}
fontRanges();
for (const image of document.querySelectorAll(imageSelector)) {
if (seen.has(image)) continue;
seen.add(image);
sawText = true;
if (image.complete) {
image.dataset.imageReady = image.naturalWidth ? 'cached' : 'fallback';
continue;
}
delete image.dataset.imageReady;
image.setAttribute('aria-busy', 'true');
busy.set(image, 'imageReady');
pending++;
const dispose = () => {
image.removeEventListener('load', loaded);
image.removeEventListener('error', failed);
imageListeners.delete(dispose);
};
const reveal = (status) => {
dispose();
if (!active) return;
release(image, status);
};
const loaded = () => {
if (image.decode) image.decode().then(() => reveal('loaded'), () => reveal('fallback'));
else reveal('loaded');
};
const failed = () => reveal('fallback');
imageListeners.add(dispose);
image.addEventListener('load', loaded, { once: true });
image.addEventListener('error', failed, { once: true });
}
for (const element of document.querySelectorAll(selector)) {
if (seen.has(element)) continue;
seen.add(element);
sawText = true;
const rect = element.getBoundingClientRect();
const style = getComputedStyle(element);
// 屏幕外文本、隐藏的 Blog 条目以及 hero 区块的背面永远不会阻塞可见页面的呈现。它们的字体仍通过 CSS 正常加载。
if (!rect.width || !rect.height || rect.bottom = window.innerHeight || style.visibility === 'hidden' || element.closest('[aria-hidden="true"], [data-font-skip]')) {
element.dataset.fontReady = 'offscreen';
continue;
}
const needed = requiredFonts(element);
const missing = needed.filter(([spec, text]) => !document.fonts.check(spec, text));
if (!missing.length) {
element.dataset.fontReady = 'cached';
continue;
}
delete element.dataset.fontReady;
element.setAttribute('aria-busy', 'true');
busy.set(element, 'fontReady');
pending++;
const promises = missing.map(([spec, text]) => {
const key = spec + text;
if (!requests.has(key)) requests.set(key, document.fonts.load(spec, text));
return requests.get(key);
});
Promise.all(promises).then(() => release(element, 'loaded'), () => release(element, 'fallback'));
}
syncInteractions();
if (sawText && pending === 0) finish();
}
function release(element, status) {
if (!active || !busy.has(element)) return;
element.dataset[busy.get(element)] = status;
element.removeAttribute('aria-busy');
busy.delete(element);
if (--pending === 0) finish();
else syncInteractions();
}
// 该计时器独立于 React 和字体 Promise 运行,包括发生错误时。
const timer = setTimeout(finish, maxWait);
const observer = new MutationObserver(scan);
cleanup = finish;
root.classList.add('home-fonts-loading');
document.querySelectorAll(selector).forEach((element) => delete element.dataset.fontReady);
observer.observe(root, { childList: true, subtree: true });
document.addEventListener('DOMContentLoaded', scan, { once: true });
scan();
}
window.__mimoHomeFonts = { start, stop };
window.addEventListener('pageshow', (event) => { if (event.persisted) stop(); });
start();
})();
document.documentElement.classList.toggle('coder-docs',false);document.documentElement.classList.toggle('mimo-site',true);document.documentElement.classList.toggle('legal-docs',false);MiMo-V2.6 | 小米
小米 MiMo v2.6 发布
小米 MiMo 系列模型官网更新至 MiMo-V2.6 版本。但页面正文主要为网站前端的字体加载与渲染脚本,未包含模型参数、性能评测或发布说明等实质性内容,实际信息量有限,具体更新细节有待官方进一步披露。
来源:Hacker News