fix local markdown resource missing tabs and title setting

This commit is contained in:
lix-2026
2026-05-24 03:01:34 +08:00
parent 6904588055
commit 6df74fb4e0
10 changed files with 132 additions and 17 deletions
+3
View File
@@ -5766,6 +5766,9 @@ fn build_page_aggregate_projection_result(
show_block_ref_count: bool_field(meta, "show_block_ref_count")
.or_else(|| bool_field(meta, "showBlockRefCount"))
.unwrap_or(false),
hide_title_header: bool_field(meta, "hide_title_header")
.or_else(|| bool_field(meta, "hideTitleHeader"))
.unwrap_or(false),
embed_default_block_id: meta
.get("embed_default_block_id")
.or_else(|| meta.get("embedDefaultBlockId"))
@@ -93,6 +93,7 @@ pub struct PageOptions {
pub page_font: String,
pub hide_child_pages: bool,
pub show_block_ref_count: bool,
pub hide_title_header: bool,
pub embed_default_block_id: Value,
}
@@ -111,6 +112,7 @@ impl Default for PageOptions {
page_font: "default".into(),
hide_child_pages: false,
show_block_ref_count: false,
hide_title_header: false,
embed_default_block_id: Value::Null,
}
}
@@ -46,6 +46,7 @@ pub struct PageAggregateBuilder {
page_font: String,
hide_child_pages: bool,
show_block_ref_count: bool,
hide_title_header: bool,
embed_default_block_id: Value,
content: Value,
revision: Value,
@@ -86,6 +87,7 @@ impl PageAggregateBuilder {
page_font: "default".to_string(),
hide_child_pages: false,
show_block_ref_count: false,
hide_title_header: false,
embed_default_block_id: Value::Null,
content: Value::Null,
revision: Value::Null,
@@ -305,6 +307,7 @@ impl PageAggregateBuilder {
page_font: self.page_font,
hide_child_pages: self.hide_child_pages,
show_block_ref_count: self.show_block_ref_count,
hide_title_header: self.hide_title_header,
embed_default_block_id: self.embed_default_block_id,
};
let layout_options = to_value(&page_options).expect("PageOptions 序列化不应失败");
@@ -1597,7 +1597,8 @@ mod tests {
"rootUri": root_uri,
"options": {
"wideLayout": true,
"showToc": false
"showToc": false,
"hideTitleHeader": false
}
})
.to_string(),
@@ -1625,6 +1626,10 @@ mod tests {
options_json["pages"][&renamed_document_id]["showToc"],
false
);
assert_eq!(
options_json["pages"][&renamed_document_id]["hideTitleHeader"],
false
);
let _ = std::fs::remove_dir_all(&root);
}
@@ -2769,12 +2769,19 @@ pub fn resolve_local_markdown_page_aggregate(
let block_count = content.as_array().map(|blocks| blocks.len()).unwrap_or(0) as u64;
let page_subtree = markdown_page_subtree(document_id, &title, &content);
let workspace_id = local_workspace_id(&canonical_root);
let page_options = metadata
let page_options_value = metadata
.page_options
.get(document_id)
.or_else(|| metadata.page_options.get(&markdown_file.relative_path))
.or_else(|| metadata.page_options.get(&markdown_file.relative_path));
let mut page_options = page_options_value
.map(page_options_from_metadata)
.unwrap_or_default();
if page_options_value
.and_then(page_options_hide_title_header_value)
.is_none()
{
page_options.hide_title_header = true;
}
let character_count = parsed.body.chars().count() as u64;
let word_count = parsed
.body
@@ -6696,9 +6703,19 @@ fn page_options_from_metadata(value: &Value) -> PageOptions {
{
options.protect_editing = protect_editing;
}
if let Some(hide_title_header) = page_options_hide_title_header_value(value) {
options.hide_title_header = hide_title_header;
}
options
}
fn page_options_hide_title_header_value(value: &Value) -> Option<bool> {
value
.get("hideTitleHeader")
.or_else(|| value.get("hide_title_header"))
.and_then(Value::as_bool)
}
pub(crate) fn local_workspace_id(root: &Path) -> String {
if let Ok(manifest) = load_local_workspace_manifest(root) {
if !manifest.workspace_id.trim().is_empty() {
@@ -8294,7 +8311,7 @@ mod tests {
std::fs::write(root.join("README.md"), "# Local Options\n").expect("write md");
std::fs::write(
root.join(".mnote").join("page-options.json"),
r#"{"version":1,"pages":{"local-md:README.md":{"wideLayout":true,"showToc":true,"showHeadingNumbers":true}}}"#,
r#"{"version":1,"pages":{"local-md:README.md":{"wideLayout":true,"showToc":true,"showHeadingNumbers":true,"hideTitleHeader":false}}}"#,
)
.expect("write options");
let root_uri = format!("file://{}", root.display());
@@ -8304,6 +8321,7 @@ mod tests {
assert!(aggregate.layout.page_options.wide_layout);
assert!(aggregate.layout.page_options.show_toc);
assert!(aggregate.layout.page_options.show_heading_numbers);
assert!(!aggregate.layout.page_options.hide_title_header);
let _ = std::fs::remove_dir_all(&root);
}
@@ -10236,6 +10254,7 @@ fn main() {}
let aggregate = resolve_local_markdown_page_aggregate(&root_uri, "local-md:File~20Name.md")
.expect("aggregate");
assert_eq!(aggregate.title, "File Name");
assert!(aggregate.layout.page_options.hide_title_header);
let _ = std::fs::remove_dir_all(&root);
}
@@ -222,8 +222,8 @@ pub async fn document_page_shell(
secondary_workspace_id={secondary_aggregate.as_ref().map(|aggregate| aggregate.identity.workspace_id.clone()).unwrap_or_default()}
secondary_page_subtree_json={secondary_page_subtree_json.unwrap_or_default()}
secondary_page_options_json={secondary_page_options_json.unwrap_or_default()}
primary_hide_title_header={is_local_folder}
secondary_hide_title_header={secondary_source_kind == Some("local_folder")}
primary_hide_title_header={aggregate.layout.page_options.hide_title_header}
secondary_hide_title_header={secondary_aggregate.as_ref().map(|aggregate| aggregate.layout.page_options.hide_title_header).unwrap_or(secondary_source_kind == Some("local_folder"))}
show_admin_access_policy={is_local_access_policy_admin_context(&context)}
/>
});
@@ -4185,7 +4185,7 @@ pub(crate) fn render_editor_island_adapter_script() -> &'static str {
} catch (error) {
console.warn('mnote resource tab 打开失败', error);
markResourceTabError(entry);
return false;
return true;
}
};
+13 -1
View File
@@ -501,6 +501,7 @@ const SIDEBAR_TREE_JS: &str = r##"
pageFont: 'default',
hideChildPages: false,
showBlockRefCount: false,
hideTitleHeader: false,
embedDefaultBlockId: null
};
}
@@ -545,12 +546,14 @@ const SIDEBAR_TREE_JS: &str = r##"
|| name === 'smallText'
|| name === 'layoutDensity'
|| name === 'pageFont'
|| name === 'showHeadingNumbers';
|| name === 'showHeadingNumbers'
|| (name === 'hideTitleHeader' && currentSourceKind() === 'local_folder');
}
function pageOptionDescription(name) {
if (name === 'wideLayout') return '';
if (name === 'smallText') return '';
if (name === 'hideTitleHeader') return ' Markdown ';
if (name === 'showToc') return '';
if (name === 'showHeadingNumbers') return '';
if (name === 'protectEditing') return '';
@@ -564,6 +567,7 @@ const SIDEBAR_TREE_JS: &str = r##"
if (name === 'wideLayout') return '';
if (name === 'smallText') return '';
if (name === 'showHeadingNumbers') return '';
if (name === 'hideTitleHeader') return ' Markdown ';
if (name === 'layoutDensity') return '';
if (name === 'pageFont') return '';
if (name === 'showToc') return '线 Rust ';
@@ -663,6 +667,13 @@ const SIDEBAR_TREE_JS: &str = r##"
document.documentElement.setAttribute('data-page-font', String(options.pageFont || 'default'));
document.documentElement.setAttribute('data-global-show-heading-numbers', String(globalShowHeadingNumbers));
document.documentElement.setAttribute('data-page-show-heading-numbers', String(showHeadingNumbers));
document.documentElement.setAttribute('data-page-hide-title-header', String(Boolean(options.hideTitleHeader)));
var titleHeader = document.querySelector('.document-pane[data-pane-role="primary"] .document-shell-header') || document.querySelector('.document-shell-header');
if (titleHeader instanceof HTMLElement) {
var hidden = Boolean(options.hideTitleHeader);
titleHeader.hidden = hidden;
titleHeader.setAttribute('data-page-title-hidden', String(hidden));
}
}
function normalizeSidebarTreeMode(value) {
@@ -8358,6 +8369,7 @@ const SIDEBAR_TREE_JS: &str = r##"
createPageOptionRow('smallText', 'checkbox') +
createPageOptionRow('showToc', 'checkbox') +
createPageOptionRow('protectEditing', 'checkbox') +
createPageOptionRow('hideTitleHeader', 'checkbox') +
'</div>' +
'<div class="wolai-page-settings-section" data-page-settings-panel="custom" hidden>' +
createPageFontRow() +