feat: consolidate local-first mnote web runtime

This commit is contained in:
lix-2026
2026-05-28 22:01:44 +08:00
parent 7354807ee9
commit 39b9a0183a
154 changed files with 13591 additions and 12728 deletions
+267 -32
View File
@@ -1651,8 +1651,8 @@ body {
.sidebar-tree .tree-row[data-active="true"],
.sidebar-tree .tree-row[data-selected="true"] {
background: rgba(255, 71, 71, 0.1);
color: #E0525B;
background: rgba(55, 53, 47, 0.08);
color: #2D2E2E;
}
.sidebar-tree .tree-row[data-drop-feedback="true"],
@@ -1676,26 +1676,30 @@ body {
align-items: center;
justify-content: center;
line-height: 1;
font-size: 0;
}
.sidebar-tree .tree-toggle:hover {
background: rgba(27, 28, 28, 0.06);
}
.sidebar-tree .tree-toggle-icon {
width: 20px;
height: 20px;
.sidebar-tree .tree-toggle::before {
content: "";
width: 0;
height: 0;
border-top: 4px solid transparent;
border-bottom: 4px solid transparent;
border-left: 5px solid currentColor;
display: block;
fill: #878787;
transform-origin: 50% 50%;
}
.sidebar-tree .tree-toggle[aria-expanded="true"] .tree-toggle-icon {
.sidebar-tree .tree-row[aria-expanded="true"] > .tree-toggle::before {
transform: rotate(90deg);
}
.sidebar-tree .tree-row[data-active="true"] .tree-toggle-icon {
fill: #CF5659;
.sidebar-tree .tree-row[data-active="true"] .tree-toggle {
color: #8F8A84;
}
.sidebar-tree:not([data-tree-shell-mode="filetree"]) .tree-kind-badge[data-kind="page"] {
@@ -1703,58 +1707,137 @@ body {
}
.sidebar-tree .tree-kind-badge {
--mnote-filetree-icon-file: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 2h7l3 3v9H3zM10 2v3h3' fill='none' stroke='black' stroke-width='1.4'/%3E%3C/svg%3E");
--mnote-filetree-icon-folder: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M1 4h5l1 2h8v8H1z' fill='none' stroke='black' stroke-width='1.4'/%3E%3C/svg%3E");
--mnote-filetree-icon-markdown: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 2h5l3 3v9H4zM9 2v3h3M6 8h4M6 10h4M6 12h2' fill='none' stroke='black' stroke-width='1.35'/%3E%3C/svg%3E");
--mnote-filetree-icon-table: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M1.5 2.5h13v11h-13zM1.5 6h13M1.5 9.5h13M6 2.5v11m4-11v11' fill='none' stroke='black' stroke-width='1.4'/%3E%3C/svg%3E");
--mnote-filetree-icon-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M1.5 3h13v10h-13zM3 11l3-3 2 2 2-2 3 3M5 6h.1' fill='none' stroke='black' stroke-width='1.4'/%3E%3C/svg%3E");
--mnote-filetree-icon-mindmap: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 4h3v3H3zM10 2h3v3h-3zM10 11h3v3h-3zM6 6l4-2M6 6l4 6' fill='none' stroke='black' stroke-width='1.4'/%3E%3C/svg%3E");
--mnote-filetree-icon-pdf: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 2h7l3 3v9H3zM4.5 9h7M4.5 11h7M10 2v3h3' fill='none' stroke='black' stroke-width='1.4'/%3E%3C/svg%3E");
--mnote-filetree-icon-word: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 2h10v12H3zM5 5h6M5 8h6M5 11h4' fill='none' stroke='black' stroke-width='1.4'/%3E%3C/svg%3E");
--mnote-filetree-icon-ppt: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M2 3h12v8H2zM5 14h6M8 11v3M5 6h6M5 8h4' fill='none' stroke='black' stroke-width='1.4'/%3E%3C/svg%3E");
--mnote-filetree-icon-sheet: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M2 2h12v12H2zM2 6h12M2 10h12M6 2v12m4-12v12' fill='none' stroke='black' stroke-width='1.4'/%3E%3C/svg%3E");
--mnote-filetree-icon-code: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M5 5 2 8l3 3V9H4V7h1zm6 0v2h1v2h-1v2l3-3zm-2-2H7L5 13h2z'/%3E%3C/svg%3E");
--mnote-filetree-icon-web: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M2 3h12v10H2zm1 3v6h10V6zm0-2v1h10V4z'/%3E%3C/svg%3E");
--mnote-filetree-icon-config: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 4h10v2H3zm0 3h10v2H3zm0 3h10v2H3zM5 3h2v4H5zm4 3h2v4H9z'/%3E%3C/svg%3E");
--mnote-filetree-icon-office: var(--mnote-filetree-icon-word);
--mnote-filetree-icon-mask: var(--mnote-filetree-icon-file);
width: 20px;
height: 20px;
display: inline-flex;
align-items: center;
justify-content: center;
flex: 0 0 20px;
color: #111111;
font-size: 15px;
color: #9A958F;
overflow: hidden;
}
.sidebar-tree .tree-kind-badge::before {
content: "";
font-family: var(--wolai-font-sans);
font-size: 18px;
line-height: 1;
content: "";
width: 14px;
height: 14px;
display: block;
background: currentColor;
-webkit-mask: var(--mnote-filetree-icon-mask) center / contain no-repeat;
mask: var(--mnote-filetree-icon-mask) center / contain no-repeat;
}
.sidebar-tree .tree-kind-badge[data-kind="page"]::before {
content: "";
--mnote-filetree-icon-mask: var(--mnote-filetree-icon-file);
}
.sidebar-tree[data-tree-shell-mode="filetree"] .tree-kind-badge[data-kind="page"]::before,
.sidebar-tree .tree-kind-badge[data-kind="document"]::before {
content: "◇";
--mnote-filetree-icon-mask: var(--mnote-filetree-icon-file);
}
.sidebar-tree .tree-kind-badge[data-kind="index"]::before {
content: "▤";
color: var(--atelier-secondary);
.sidebar-tree .tree-kind-badge[data-kind="index"]::before,
.sidebar-tree .tree-kind-badge[data-kind="markdown"]::before {
--mnote-filetree-icon-mask: var(--mnote-filetree-icon-markdown);
}
.sidebar-tree .tree-kind-badge[data-kind="index"],
.sidebar-tree .tree-kind-badge[data-kind="markdown"],
.sidebar-tree .tree-kind-badge[data-kind="code"] {
color: #111111;
}
.sidebar-tree .tree-kind-badge[data-kind="code"]::before { --mnote-filetree-icon-mask: var(--mnote-filetree-icon-code); }
.sidebar-tree .tree-kind-badge[data-kind="web"]::before { --mnote-filetree-icon-mask: var(--mnote-filetree-icon-web); }
.sidebar-tree .tree-kind-badge[data-kind="config"]::before { --mnote-filetree-icon-mask: var(--mnote-filetree-icon-config); }
.sidebar-tree .tree-kind-badge[data-kind="folder"]::before,
.sidebar-tree .tree-kind-badge[data-kind="asset_folder"]::before {
content: "▱";
color: #D08A1F;
--mnote-filetree-icon-mask: var(--mnote-filetree-icon-folder);
}
.sidebar-tree .tree-kind-badge[data-kind="folder"],
.sidebar-tree .tree-kind-badge[data-kind="asset_folder"] {
color: #B8751A;
}
.sidebar-tree .tree-kind-badge[data-kind="image"] {
color: #5B6CF0;
}
.sidebar-tree .tree-kind-badge[data-kind="image"]::before {
content: "▧";
color: #5B7CFA;
--mnote-filetree-icon-mask: var(--mnote-filetree-icon-image);
}
.sidebar-tree .tree-kind-badge[data-kind="mindmap"] {
color: #4F8F68;
}
.sidebar-tree .tree-kind-badge[data-kind="mindmap"]::before {
content: "⌘";
color: #31AA4D;
--mnote-filetree-icon-mask: var(--mnote-filetree-icon-mindmap);
}
.sidebar-tree .tree-kind-badge[data-kind="table"]::before,
.sidebar-tree .tree-kind-badge[data-kind="luckysheet"]::before {
content: "▦";
color: #2367F6;
.sidebar-tree .tree-kind-badge[data-kind="pdf"]::before {
--mnote-filetree-icon-mask: var(--mnote-filetree-icon-pdf);
}
.sidebar-tree .tree-kind-badge[data-kind="pdf"] {
color: #E74C3C;
}
.sidebar-tree .tree-kind-badge[data-kind="office"]::before,
.sidebar-tree .tree-kind-badge[data-kind="onlyoffice"]::before,
.sidebar-tree .tree-kind-badge[data-kind="word"]::before {
--mnote-filetree-icon-mask: var(--mnote-filetree-icon-word);
}
.sidebar-tree .tree-kind-badge[data-kind="ppt"]::before,
.sidebar-tree .tree-kind-badge[data-kind="presentation"]::before {
--mnote-filetree-icon-mask: var(--mnote-filetree-icon-ppt);
}
.sidebar-tree .tree-kind-badge[data-kind="sheet"]::before {
--mnote-filetree-icon-mask: var(--mnote-filetree-icon-sheet);
}
.sidebar-tree .tree-kind-badge[data-kind="office"],
.sidebar-tree .tree-kind-badge[data-kind="onlyoffice"],
.sidebar-tree .tree-kind-badge[data-kind="web"],
.sidebar-tree .tree-kind-badge[data-kind="word"] {
color: #4F7DF3;
}
.sidebar-tree .tree-kind-badge[data-kind="ppt"],
.sidebar-tree .tree-kind-badge[data-kind="presentation"] {
color: #D94841;
}
.sidebar-tree .tree-kind-badge[data-kind="sheet"] {
color: #2F9E44;
}
.sidebar-tree .tree-kind-badge[data-kind="table"]::before {
--mnote-filetree-icon-mask: var(--mnote-filetree-icon-table);
}
.sidebar-tree .tree-kind-badge[data-kind="table"],
.sidebar-tree .tree-kind-badge[data-kind="config"] {
color: #5572A2;
}
.sidebar-tree .tree-link {
@@ -2357,6 +2440,93 @@ body {
grid-template-columns: minmax(0, 1fr) var(--mnote-secondary-pane-resizer-width) var(--mnote-secondary-pane-width);
}
.mnote-navigation-page-host {
width: 100%;
height: 100%;
min-width: 0;
min-height: 0;
overflow: auto;
background: var(--wolai-bg-main);
}
.mnote-navigation-page {
width: min(960px, calc(100% - 64px));
margin: 0 auto;
padding: 56px 0 96px;
}
.mnote-navigation-page__header {
margin-bottom: 28px;
}
.mnote-navigation-page__header h1 {
margin: 0;
font-size: 28px;
font-weight: 650;
line-height: 1.25;
color: var(--wolai-text-primary);
}
.mnote-navigation-page__header p {
margin: 8px 0 0;
color: var(--wolai-text-secondary);
font-size: 13px;
line-height: 1.5;
overflow-wrap: anywhere;
}
.mnote-navigation-page__section {
margin-top: 24px;
}
.mnote-navigation-page__notice {
margin: 0 0 20px;
padding: 10px 12px;
border: 1px solid rgba(210, 180, 90, 0.42);
border-radius: 6px;
background: rgba(255, 247, 221, 0.72);
color: var(--wolai-text-primary);
font-size: 13px;
line-height: 1.5;
}
.mnote-navigation-page__notice span {
display: block;
margin-top: 4px;
color: var(--wolai-text-secondary);
overflow-wrap: anywhere;
}
.mnote-navigation-page__section h2 {
margin: 0 0 10px;
font-size: 13px;
font-weight: 650;
color: var(--wolai-text-secondary);
}
.mnote-navigation-page__section p {
margin: 0;
color: var(--wolai-text-secondary);
font-size: 13px;
}
.mnote-navigation-page__item {
display: flex;
align-items: center;
min-height: 34px;
padding: 6px 8px;
border-radius: 6px;
color: var(--wolai-text-primary);
font-size: 14px;
line-height: 1.4;
text-decoration: none;
overflow-wrap: anywhere;
}
.mnote-navigation-page__item:hover {
background: var(--wolai-bg-sidebar);
}
.document-main-editor-group {
min-width: 0;
min-height: 0;
@@ -4236,6 +4406,20 @@ button.wolai-page-ai-message-text {
background: #FFF;
}
.wolai-page-ai-agent-selector,
.wolai-page-ai-context-refs,
.wolai-page-ai-allowed-roots {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 6px;
padding: 6px 8px 0;
}
.wolai-page-ai-allowed-roots {
padding-top: 4px;
}
.wolai-page-ai-composer:focus-within {
border-color: rgba(27, 28, 28, 0.32);
}
@@ -4515,11 +4699,62 @@ mod tests {
assert!(MNOTE_CSS.contains(".mnote-tree-context-menu"));
}
#[test]
fn sidebar_filetree_icons_use_css_masks_instead_of_text_glyphs() {
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-file"));
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-folder"));
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-markdown"));
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-table"));
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-image"));
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-mindmap"));
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-pdf"));
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-office"));
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-word"));
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-ppt"));
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-sheet"));
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-code"));
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-web"));
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-config"));
assert!(MNOTE_CSS.contains("xmlns='http://www.w3.org/2000/svg'"));
assert!(
MNOTE_CSS.contains("mask: var(--mnote-filetree-icon-mask) center / contain no-repeat")
);
assert!(
MNOTE_CSS.contains("--mnote-filetree-icon-mask: var(--mnote-filetree-icon-folder);")
);
assert!(
MNOTE_CSS.contains("--mnote-filetree-icon-mask: var(--mnote-filetree-icon-markdown);")
);
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-mask: var(--mnote-filetree-icon-table);"));
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-mask: var(--mnote-filetree-icon-image);"));
assert!(
MNOTE_CSS.contains("--mnote-filetree-icon-mask: var(--mnote-filetree-icon-mindmap);")
);
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-mask: var(--mnote-filetree-icon-pdf);"));
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-mask: var(--mnote-filetree-icon-word);"));
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-mask: var(--mnote-filetree-icon-ppt);"));
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-mask: var(--mnote-filetree-icon-sheet);"));
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-mask: var(--mnote-filetree-icon-code);"));
assert!(MNOTE_CSS.contains("--mnote-filetree-icon-mask: var(--mnote-filetree-icon-web);"));
assert!(
MNOTE_CSS.contains("--mnote-filetree-icon-mask: var(--mnote-filetree-icon-config);")
);
let retired_table_engine = ["lucky", "sheet"].concat();
assert!(!MNOTE_CSS.contains(&retired_table_engine));
assert!(MNOTE_CSS.contains("color: #4F7DF3;"));
assert!(MNOTE_CSS.contains("color: #D94841;"));
assert!(MNOTE_CSS.contains("color: #2F9E44;"));
assert!(MNOTE_CSS.contains("color: #E74C3C;"));
assert!(!MNOTE_CSS.contains(
"font-family: var(--wolai-font-sans);\n font-size: 18px;\n line-height: 1;\n}"
));
}
#[test]
fn mnote_css_is_reasonably_sized() {
// 至少 2000 字符才能包含完整样式
assert!(MNOTE_CSS.len() > 2000);
// 当前整合了工作区壳、编辑器样式、树菜单、页面 AI、账号弹窗与授权管理控制面,仍保持在单文件可审阅范围内。
assert!(MNOTE_CSS.len() < 110000);
// 当前整合了工作区壳、编辑器样式、树菜单、文件树图标、页面 AI、账号弹窗与授权管理控制面,仍保持在单文件可审阅范围内。
assert!(MNOTE_CSS.len() < 114000);
}
}