refactor: split document pane runtime
This commit is contained in:
+1
-1
@@ -119,7 +119,7 @@ cargo test --manifest-path rust/Cargo.toml -p mnote-web --lib routes::tests::mno
|
|||||||
|
|
||||||
拆分项:
|
拆分项:
|
||||||
|
|
||||||
- [ ] B1. `document-pane-runtime.js`:secondary pane URL、pane resize、pane close、pane runtime registry。
|
- [x] B1. `document-pane-runtime.js`:secondary pane URL、pane resize、pane close、pane runtime registry。
|
||||||
- [x] B2. `document-tiptap-conversion-runtime.js`:legacy block / inline content / marks 转 Tiptap document。
|
- [x] B2. `document-tiptap-conversion-runtime.js`:legacy block / inline content / marks 转 Tiptap document。
|
||||||
- [ ] B3. `document-resource-tab-runtime.js`:resource tab registry、MRU、close guard、resource text/image/frame editor mount。
|
- [ ] B3. `document-resource-tab-runtime.js`:resource tab registry、MRU、close guard、resource text/image/frame editor mount。
|
||||||
- [ ] B4. `document-mindmap-host-runtime.js`:primary mindmap object shell、mindmap resource tab mount/unmount。
|
- [ ] B4. `document-mindmap-host-runtime.js`:primary mindmap object shell、mindmap resource tab mount/unmount。
|
||||||
|
|||||||
@@ -1,3 +1,14 @@
|
|||||||
|
import {
|
||||||
|
buildPaneRuntime,
|
||||||
|
clearSecondaryParams,
|
||||||
|
createSecondaryPaneWidthController,
|
||||||
|
currentUrl,
|
||||||
|
installSecondaryPaneCloseButtons,
|
||||||
|
installSecondaryPaneOpenListeners,
|
||||||
|
pushUrlState,
|
||||||
|
replaceUrlState,
|
||||||
|
secondaryQueryParamNames,
|
||||||
|
} from './document-pane-runtime.js';
|
||||||
import {
|
import {
|
||||||
conflictDetectionKeyBelongsToSession,
|
conflictDetectionKeyBelongsToSession,
|
||||||
conflictDetectionKeyFromBody,
|
conflictDetectionKeyFromBody,
|
||||||
@@ -37,154 +48,15 @@ import {
|
|||||||
const panesBootstrap = parseJsonScript(PANES_BOOTSTRAP_ID);
|
const panesBootstrap = parseJsonScript(PANES_BOOTSTRAP_ID);
|
||||||
if (!panesBootstrap || !Array.isArray(panesBootstrap.panes)) return;
|
if (!panesBootstrap || !Array.isArray(panesBootstrap.panes)) return;
|
||||||
|
|
||||||
const paneRouteConfig = {
|
|
||||||
primary: {
|
|
||||||
sourceKindParam: 'sourceKind',
|
|
||||||
rootUriParam: 'rootUri',
|
|
||||||
secondary: false,
|
|
||||||
},
|
|
||||||
secondary: {
|
|
||||||
documentIdParam: 'secondaryDocumentId',
|
|
||||||
sourceKindParam: 'secondarySourceKind',
|
|
||||||
rootUriParam: 'secondaryRootUri',
|
|
||||||
secondary: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const secondaryQueryParamNames = [
|
|
||||||
paneRouteConfig.secondary.documentIdParam,
|
|
||||||
paneRouteConfig.secondary.sourceKindParam,
|
|
||||||
paneRouteConfig.secondary.rootUriParam,
|
|
||||||
];
|
|
||||||
const currentUrl = () => new URL(window.location.href);
|
|
||||||
const replaceUrlState = (url) => {
|
|
||||||
window.history.replaceState({}, '', url.pathname + url.search + url.hash);
|
|
||||||
};
|
|
||||||
const pushUrlState = (url) => {
|
|
||||||
window.history.pushState({}, '', url.pathname + url.search + url.hash);
|
|
||||||
};
|
|
||||||
const clearSecondaryParams = () => {
|
|
||||||
const url = currentUrl();
|
|
||||||
secondaryQueryParamNames.forEach((name) => url.searchParams.delete(name));
|
|
||||||
replaceUrlState(url);
|
|
||||||
};
|
|
||||||
if (panesBootstrap.secondaryInvalid === true) clearSecondaryParams();
|
if (panesBootstrap.secondaryInvalid === true) clearSecondaryParams();
|
||||||
|
installSecondaryPaneOpenListeners();
|
||||||
const secondaryUrlForDocument = (documentId, detail = {}) => {
|
installSecondaryPaneCloseButtons();
|
||||||
const url = currentUrl();
|
const { applyStoredSecondaryWidth } = createSecondaryPaneWidthController();
|
||||||
url.searchParams.set(paneRouteConfig.secondary.documentIdParam, documentId);
|
|
||||||
const detailSourceKind = typeof detail.sourceKind === 'string' ? detail.sourceKind.trim() : '';
|
|
||||||
const detailRootUri = typeof detail.rootUri === 'string' ? detail.rootUri.trim() : '';
|
|
||||||
const primarySourceKind = (url.searchParams.get(paneRouteConfig.primary.sourceKindParam) || '').trim();
|
|
||||||
const primaryRootUri = (url.searchParams.get(paneRouteConfig.primary.rootUriParam) || '').trim();
|
|
||||||
const secondarySourceKind = detailSourceKind || primarySourceKind;
|
|
||||||
const secondaryRootUri = detailRootUri || primaryRootUri;
|
|
||||||
if (secondarySourceKind) url.searchParams.set(paneRouteConfig.secondary.sourceKindParam, secondarySourceKind);
|
|
||||||
else url.searchParams.delete(paneRouteConfig.secondary.sourceKindParam);
|
|
||||||
if (secondaryRootUri) url.searchParams.set(paneRouteConfig.secondary.rootUriParam, secondaryRootUri);
|
|
||||||
else url.searchParams.delete(paneRouteConfig.secondary.rootUriParam);
|
|
||||||
return { url, sourceKind: secondarySourceKind, rootUri: secondaryRootUri };
|
|
||||||
};
|
|
||||||
|
|
||||||
const openDocumentInSecondaryPane = (documentId, detail = {}) => {
|
|
||||||
const id = typeof documentId === 'string' ? documentId.trim() : '';
|
|
||||||
if (!id) return false;
|
|
||||||
const target = secondaryUrlForDocument(id, detail);
|
|
||||||
if (typeof window.__mnoteDocumentPaneRuntime?.openSecondaryDocument === 'function') {
|
|
||||||
void window.__mnoteDocumentPaneRuntime.openSecondaryDocument({
|
|
||||||
documentId: id,
|
|
||||||
workspaceId: typeof detail.workspaceId === 'string' ? detail.workspaceId.trim() : '',
|
|
||||||
sourceKind: target.sourceKind || null,
|
|
||||||
rootUri: target.rootUri || null,
|
|
||||||
url: target.url,
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
window.location.assign(target.url.pathname + target.url.search + target.url.hash);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener('tree.page.open-right', (event) => {
|
|
||||||
const detail = event?.detail && typeof event.detail === 'object' ? event.detail : {};
|
|
||||||
const documentId = typeof detail.documentId === 'string' ? detail.documentId.trim() : '';
|
|
||||||
openDocumentInSecondaryPane(documentId, detail);
|
|
||||||
});
|
|
||||||
|
|
||||||
window.addEventListener('tree.page.open', (event) => {
|
|
||||||
const detail = event?.detail && typeof event.detail === 'object' ? event.detail : {};
|
|
||||||
const openTarget = typeof detail.openTarget === 'string' ? detail.openTarget.trim().toLowerCase() : '';
|
|
||||||
if (openTarget !== 'side') return;
|
|
||||||
const documentId = typeof detail.documentId === 'string' ? detail.documentId.trim() : '';
|
|
||||||
openDocumentInSecondaryPane(documentId, detail);
|
|
||||||
});
|
|
||||||
|
|
||||||
document.querySelectorAll('[data-mnote-pane-close="secondary"]').forEach((button) => {
|
|
||||||
button.addEventListener('click', (event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
const url = currentUrl();
|
|
||||||
secondaryQueryParamNames.forEach((name) => url.searchParams.delete(name));
|
|
||||||
if (typeof window.__mnoteDocumentPaneRuntime?.closeSecondaryDocument === 'function') {
|
|
||||||
window.__mnoteDocumentPaneRuntime.closeSecondaryDocument({ url });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
window.location.assign(url.pathname + url.search + url.hash);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const workspace = document.querySelector('[data-testid="mnote-document-workspace"]');
|
|
||||||
const resizer = document.querySelector('[data-document-pane-resizer="true"]');
|
|
||||||
const SECONDARY_WIDTH_KEY = 'mnote.document.secondary.width';
|
|
||||||
const applyStoredSecondaryWidth = () => {
|
|
||||||
if (!(workspace instanceof HTMLElement)) return;
|
|
||||||
if (workspace.getAttribute('data-has-secondary-pane') !== 'true') {
|
|
||||||
workspace.style.removeProperty('grid-template-columns');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const raw = window.localStorage ? window.localStorage.getItem(SECONDARY_WIDTH_KEY) : '';
|
|
||||||
const width = Number(raw || 0);
|
|
||||||
if (Number.isFinite(width) && width >= 320) {
|
|
||||||
workspace.style.gridTemplateColumns = `minmax(0, 1fr) 6px minmax(320px, ${Math.round(width)}px)`;
|
|
||||||
}
|
|
||||||
} catch (_) {}
|
|
||||||
};
|
|
||||||
applyStoredSecondaryWidth();
|
applyStoredSecondaryWidth();
|
||||||
if (workspace instanceof HTMLElement && resizer instanceof HTMLElement) {
|
|
||||||
resizer.addEventListener('pointerdown', (event) => {
|
|
||||||
if (workspace.getAttribute('data-has-secondary-pane') !== 'true') return;
|
|
||||||
event.preventDefault();
|
|
||||||
const move = (nextEvent) => {
|
|
||||||
const rect = workspace.getBoundingClientRect();
|
|
||||||
const width = Math.min(Math.max(320, rect.right - nextEvent.clientX), Math.max(420, rect.width - 360));
|
|
||||||
workspace.style.gridTemplateColumns = `minmax(0, 1fr) 6px minmax(320px, ${Math.round(width)}px)`;
|
|
||||||
try {
|
|
||||||
if (window.localStorage) window.localStorage.setItem(SECONDARY_WIDTH_KEY, String(Math.round(width)));
|
|
||||||
} catch (_) {}
|
|
||||||
};
|
|
||||||
const up = () => {
|
|
||||||
window.removeEventListener('pointermove', move);
|
|
||||||
window.removeEventListener('pointerup', up);
|
|
||||||
};
|
|
||||||
window.addEventListener('pointermove', move);
|
|
||||||
window.addEventListener('pointerup', up);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const buildPaneRuntime = (paneDescriptor) => {
|
const paneRuntimes = panesBootstrap.panes
|
||||||
const paneRole = typeof paneDescriptor?.role === 'string' ? paneDescriptor.role : 'primary';
|
.map((paneDescriptor) => buildPaneRuntime(paneDescriptor, ROOT_SELECTOR))
|
||||||
const paneRoot = document.querySelector(`${ROOT_SELECTOR}[data-pane-role="${paneRole}"]`);
|
.filter(Boolean);
|
||||||
const observability = document.querySelector(`[data-editor-host-observability][data-pane-role="${paneRole}"]`);
|
|
||||||
if (!(paneRoot instanceof HTMLElement)) return null;
|
|
||||||
if (!paneDescriptor?.aggregate || !paneDescriptor?.bootstrap) return null;
|
|
||||||
return {
|
|
||||||
paneRole,
|
|
||||||
root: paneRoot,
|
|
||||||
observability,
|
|
||||||
aggregate: paneDescriptor.aggregate,
|
|
||||||
bootstrap: paneDescriptor.bootstrap,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const paneRuntimes = panesBootstrap.panes.map(buildPaneRuntime).filter(Boolean);
|
|
||||||
|
|
||||||
const loadRuntime = async () => {
|
const loadRuntime = async () => {
|
||||||
if (window.__mnoteLeptosTiptapRuntimePromise) {
|
if (window.__mnoteLeptosTiptapRuntimePromise) {
|
||||||
|
|||||||
@@ -0,0 +1,158 @@
|
|||||||
|
export const paneRouteConfig = {
|
||||||
|
primary: {
|
||||||
|
sourceKindParam: 'sourceKind',
|
||||||
|
rootUriParam: 'rootUri',
|
||||||
|
secondary: false,
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
documentIdParam: 'secondaryDocumentId',
|
||||||
|
sourceKindParam: 'secondarySourceKind',
|
||||||
|
rootUriParam: 'secondaryRootUri',
|
||||||
|
secondary: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const secondaryQueryParamNames = [
|
||||||
|
paneRouteConfig.secondary.documentIdParam,
|
||||||
|
paneRouteConfig.secondary.sourceKindParam,
|
||||||
|
paneRouteConfig.secondary.rootUriParam,
|
||||||
|
];
|
||||||
|
|
||||||
|
export const currentUrl = () => new URL(window.location.href);
|
||||||
|
|
||||||
|
export const replaceUrlState = (url) => {
|
||||||
|
window.history.replaceState({}, '', url.pathname + url.search + url.hash);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const pushUrlState = (url) => {
|
||||||
|
window.history.pushState({}, '', url.pathname + url.search + url.hash);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const clearSecondaryParams = () => {
|
||||||
|
const url = currentUrl();
|
||||||
|
secondaryQueryParamNames.forEach((name) => url.searchParams.delete(name));
|
||||||
|
replaceUrlState(url);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const secondaryUrlForDocument = (documentId, detail = {}) => {
|
||||||
|
const url = currentUrl();
|
||||||
|
url.searchParams.set(paneRouteConfig.secondary.documentIdParam, documentId);
|
||||||
|
const detailSourceKind = typeof detail.sourceKind === 'string' ? detail.sourceKind.trim() : '';
|
||||||
|
const detailRootUri = typeof detail.rootUri === 'string' ? detail.rootUri.trim() : '';
|
||||||
|
const primarySourceKind = (url.searchParams.get(paneRouteConfig.primary.sourceKindParam) || '').trim();
|
||||||
|
const primaryRootUri = (url.searchParams.get(paneRouteConfig.primary.rootUriParam) || '').trim();
|
||||||
|
const secondarySourceKind = detailSourceKind || primarySourceKind;
|
||||||
|
const secondaryRootUri = detailRootUri || primaryRootUri;
|
||||||
|
if (secondarySourceKind) url.searchParams.set(paneRouteConfig.secondary.sourceKindParam, secondarySourceKind);
|
||||||
|
else url.searchParams.delete(paneRouteConfig.secondary.sourceKindParam);
|
||||||
|
if (secondaryRootUri) url.searchParams.set(paneRouteConfig.secondary.rootUriParam, secondaryRootUri);
|
||||||
|
else url.searchParams.delete(paneRouteConfig.secondary.rootUriParam);
|
||||||
|
return { url, sourceKind: secondarySourceKind, rootUri: secondaryRootUri };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const openDocumentInSecondaryPane = (documentId, detail = {}) => {
|
||||||
|
const id = typeof documentId === 'string' ? documentId.trim() : '';
|
||||||
|
if (!id) return false;
|
||||||
|
const target = secondaryUrlForDocument(id, detail);
|
||||||
|
if (typeof window.__mnoteDocumentPaneRuntime?.openSecondaryDocument === 'function') {
|
||||||
|
void window.__mnoteDocumentPaneRuntime.openSecondaryDocument({
|
||||||
|
documentId: id,
|
||||||
|
workspaceId: typeof detail.workspaceId === 'string' ? detail.workspaceId.trim() : '',
|
||||||
|
sourceKind: target.sourceKind || null,
|
||||||
|
rootUri: target.rootUri || null,
|
||||||
|
url: target.url,
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
window.location.assign(target.url.pathname + target.url.search + target.url.hash);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const installSecondaryPaneOpenListeners = () => {
|
||||||
|
window.addEventListener('tree.page.open-right', (event) => {
|
||||||
|
const detail = event?.detail && typeof event.detail === 'object' ? event.detail : {};
|
||||||
|
const documentId = typeof detail.documentId === 'string' ? detail.documentId.trim() : '';
|
||||||
|
openDocumentInSecondaryPane(documentId, detail);
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('tree.page.open', (event) => {
|
||||||
|
const detail = event?.detail && typeof event.detail === 'object' ? event.detail : {};
|
||||||
|
const openTarget = typeof detail.openTarget === 'string' ? detail.openTarget.trim().toLowerCase() : '';
|
||||||
|
if (openTarget !== 'side') return;
|
||||||
|
const documentId = typeof detail.documentId === 'string' ? detail.documentId.trim() : '';
|
||||||
|
openDocumentInSecondaryPane(documentId, detail);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const installSecondaryPaneCloseButtons = () => {
|
||||||
|
document.querySelectorAll('[data-mnote-pane-close="secondary"]').forEach((button) => {
|
||||||
|
button.addEventListener('click', (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
const url = currentUrl();
|
||||||
|
secondaryQueryParamNames.forEach((name) => url.searchParams.delete(name));
|
||||||
|
if (typeof window.__mnoteDocumentPaneRuntime?.closeSecondaryDocument === 'function') {
|
||||||
|
window.__mnoteDocumentPaneRuntime.closeSecondaryDocument({ url });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.location.assign(url.pathname + url.search + url.hash);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createSecondaryPaneWidthController = () => {
|
||||||
|
const workspace = document.querySelector('[data-testid="mnote-document-workspace"]');
|
||||||
|
const resizer = document.querySelector('[data-document-pane-resizer="true"]');
|
||||||
|
const secondaryWidthKey = 'mnote.document.secondary.width';
|
||||||
|
const applyStoredSecondaryWidth = () => {
|
||||||
|
if (!(workspace instanceof HTMLElement)) return;
|
||||||
|
if (workspace.getAttribute('data-has-secondary-pane') !== 'true') {
|
||||||
|
workspace.style.removeProperty('grid-template-columns');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const raw = window.localStorage ? window.localStorage.getItem(secondaryWidthKey) : '';
|
||||||
|
const width = Number(raw || 0);
|
||||||
|
if (Number.isFinite(width) && width >= 320) {
|
||||||
|
workspace.style.gridTemplateColumns = `minmax(0, 1fr) 6px minmax(320px, ${Math.round(width)}px)`;
|
||||||
|
}
|
||||||
|
} catch (_) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (workspace instanceof HTMLElement && resizer instanceof HTMLElement) {
|
||||||
|
resizer.addEventListener('pointerdown', (event) => {
|
||||||
|
if (workspace.getAttribute('data-has-secondary-pane') !== 'true') return;
|
||||||
|
event.preventDefault();
|
||||||
|
const move = (nextEvent) => {
|
||||||
|
const rect = workspace.getBoundingClientRect();
|
||||||
|
const width = Math.min(Math.max(320, rect.right - nextEvent.clientX), Math.max(420, rect.width - 360));
|
||||||
|
workspace.style.gridTemplateColumns = `minmax(0, 1fr) 6px minmax(320px, ${Math.round(width)}px)`;
|
||||||
|
try {
|
||||||
|
if (window.localStorage) window.localStorage.setItem(secondaryWidthKey, String(Math.round(width)));
|
||||||
|
} catch (_) {}
|
||||||
|
};
|
||||||
|
const up = () => {
|
||||||
|
window.removeEventListener('pointermove', move);
|
||||||
|
window.removeEventListener('pointerup', up);
|
||||||
|
};
|
||||||
|
window.addEventListener('pointermove', move);
|
||||||
|
window.addEventListener('pointerup', up);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return { applyStoredSecondaryWidth };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const buildPaneRuntime = (paneDescriptor, rootSelector) => {
|
||||||
|
const paneRole = typeof paneDescriptor?.role === 'string' ? paneDescriptor.role : 'primary';
|
||||||
|
const paneRoot = document.querySelector(`${rootSelector}[data-pane-role="${paneRole}"]`);
|
||||||
|
const observability = document.querySelector(`[data-editor-host-observability][data-pane-role="${paneRole}"]`);
|
||||||
|
if (!(paneRoot instanceof HTMLElement)) return null;
|
||||||
|
if (!paneDescriptor?.aggregate || !paneDescriptor?.bootstrap) return null;
|
||||||
|
return {
|
||||||
|
paneRole,
|
||||||
|
root: paneRoot,
|
||||||
|
observability,
|
||||||
|
aggregate: paneDescriptor.aggregate,
|
||||||
|
bootstrap: paneDescriptor.bootstrap,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -142,6 +142,10 @@ pub fn build_router(state: AppState) -> Router {
|
|||||||
"/api/mnote-browser-runtime/document-conflict-panel-runtime.js",
|
"/api/mnote-browser-runtime/document-conflict-panel-runtime.js",
|
||||||
get(web_shell::document_conflict_panel_runtime_asset),
|
get(web_shell::document_conflict_panel_runtime_asset),
|
||||||
)
|
)
|
||||||
|
.route(
|
||||||
|
"/api/mnote-browser-runtime/document-pane-runtime.js",
|
||||||
|
get(web_shell::document_pane_runtime_asset),
|
||||||
|
)
|
||||||
.route(
|
.route(
|
||||||
"/api/mnote-browser-runtime/document-tiptap-conversion-runtime.js",
|
"/api/mnote-browser-runtime/document-tiptap-conversion-runtime.js",
|
||||||
get(web_shell::document_tiptap_conversion_runtime_asset),
|
get(web_shell::document_tiptap_conversion_runtime_asset),
|
||||||
@@ -563,6 +567,7 @@ mod tests {
|
|||||||
"/api/mnote-browser-runtime/tree-live-controller.js",
|
"/api/mnote-browser-runtime/tree-live-controller.js",
|
||||||
"/api/mnote-browser-runtime/tree-shell-runtime.js",
|
"/api/mnote-browser-runtime/tree-shell-runtime.js",
|
||||||
"/api/mnote-browser-runtime/document-conflict-panel-runtime.js",
|
"/api/mnote-browser-runtime/document-conflict-panel-runtime.js",
|
||||||
|
"/api/mnote-browser-runtime/document-pane-runtime.js",
|
||||||
"/api/mnote-browser-runtime/document-tiptap-conversion-runtime.js",
|
"/api/mnote-browser-runtime/document-tiptap-conversion-runtime.js",
|
||||||
"/api/mnote-browser-runtime/document-editor-adapter-runtime.js",
|
"/api/mnote-browser-runtime/document-editor-adapter-runtime.js",
|
||||||
] {
|
] {
|
||||||
|
|||||||
@@ -855,6 +855,20 @@ pub async fn document_conflict_panel_runtime_asset() -> Response {
|
|||||||
.unwrap_or_else(|_| Response::new(Body::empty()))
|
.unwrap_or_else(|_| Response::new(Body::empty()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn document_pane_runtime_asset() -> Response {
|
||||||
|
const JS: &str = include_str!("../../browser/document-pane-runtime.js");
|
||||||
|
Response::builder()
|
||||||
|
.status(StatusCode::OK)
|
||||||
|
.header(
|
||||||
|
header::CONTENT_TYPE,
|
||||||
|
"application/javascript; charset=utf-8",
|
||||||
|
)
|
||||||
|
.header(header::CACHE_CONTROL, "no-store")
|
||||||
|
.header(HEADER_MNOTE_WEB_OWNER, "mnote-web")
|
||||||
|
.body(Body::from(JS))
|
||||||
|
.unwrap_or_else(|_| Response::new(Body::empty()))
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn document_tiptap_conversion_runtime_asset() -> Response {
|
pub async fn document_tiptap_conversion_runtime_asset() -> Response {
|
||||||
const JS: &str = include_str!("../../browser/document-tiptap-conversion-runtime.js");
|
const JS: &str = include_str!("../../browser/document-tiptap-conversion-runtime.js");
|
||||||
Response::builder()
|
Response::builder()
|
||||||
@@ -1292,6 +1306,7 @@ mod tests {
|
|||||||
|
|
||||||
const DOCUMENT_EDITOR_ADAPTER_RUNTIME_JS: &str =
|
const DOCUMENT_EDITOR_ADAPTER_RUNTIME_JS: &str =
|
||||||
include_str!("../../browser/document-editor-adapter-runtime.js");
|
include_str!("../../browser/document-editor-adapter-runtime.js");
|
||||||
|
const DOCUMENT_PANE_RUNTIME_JS: &str = include_str!("../../browser/document-pane-runtime.js");
|
||||||
const DOCUMENT_TIPTAP_CONVERSION_RUNTIME_JS: &str =
|
const DOCUMENT_TIPTAP_CONVERSION_RUNTIME_JS: &str =
|
||||||
include_str!("../../browser/document-tiptap-conversion-runtime.js");
|
include_str!("../../browser/document-tiptap-conversion-runtime.js");
|
||||||
|
|
||||||
@@ -2041,6 +2056,9 @@ mod tests {
|
|||||||
assert!(DOCUMENT_EDITOR_ADAPTER_RUNTIME_JS.contains("PANES_BOOTSTRAP_ID"));
|
assert!(DOCUMENT_EDITOR_ADAPTER_RUNTIME_JS.contains("PANES_BOOTSTRAP_ID"));
|
||||||
assert!(DOCUMENT_EDITOR_ADAPTER_RUNTIME_JS.contains("ROOT_SELECTOR"));
|
assert!(DOCUMENT_EDITOR_ADAPTER_RUNTIME_JS.contains("ROOT_SELECTOR"));
|
||||||
assert!(DOCUMENT_EDITOR_ADAPTER_RUNTIME_JS.contains("BRIDGE_PROTOCOL"));
|
assert!(DOCUMENT_EDITOR_ADAPTER_RUNTIME_JS.contains("BRIDGE_PROTOCOL"));
|
||||||
|
assert!(DOCUMENT_EDITOR_ADAPTER_RUNTIME_JS.contains("document-pane-runtime.js"));
|
||||||
|
assert!(DOCUMENT_PANE_RUNTIME_JS.contains("openDocumentInSecondaryPane"));
|
||||||
|
assert!(DOCUMENT_PANE_RUNTIME_JS.contains("buildPaneRuntime"));
|
||||||
assert!(
|
assert!(
|
||||||
DOCUMENT_EDITOR_ADAPTER_RUNTIME_JS.contains("document-tiptap-conversion-runtime.js")
|
DOCUMENT_EDITOR_ADAPTER_RUNTIME_JS.contains("document-tiptap-conversion-runtime.js")
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user