feat(editor): align selection popup and all editor control elements styling with Reader #81
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,20 +1,20 @@
|
||||
// Map to keep track of active Crepe editor instances by elementId (container ID)
|
||||
const editors = new Map();
|
||||
const editorCache = new Map();
|
||||
|
||||
/**
|
||||
* Asynchronously injects a stylesheet link tag into the document head
|
||||
* and returns a Promise that resolves when the stylesheet is fully loaded.
|
||||
*/
|
||||
async function injectStylesheet(url) {
|
||||
if (document.querySelector(`link[href="${url}"]`)) {
|
||||
async function ensureStylesheet(href) {
|
||||
if (document.querySelector(`link[href="${href}"]`)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
const link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.href = url;
|
||||
link.href = href;
|
||||
link.onload = () => resolve();
|
||||
link.onerror = (err) => reject(new Error(`Failed to load stylesheet: ${url}. ${err}`));
|
||||
link.onerror = (err) => reject(new Error(`Failed to load stylesheet: ${href}. ${err}`));
|
||||
document.head.appendChild(link);
|
||||
});
|
||||
}
|
||||
@@ -31,13 +31,16 @@ export async function initEditor(elementId, dotNetHelper, initialMarkdown) {
|
||||
|
||||
try {
|
||||
// Condition 2: Prevent FOUC by loading stylesheets before instantiating the editor
|
||||
await Promise.all([
|
||||
injectStylesheet('https://esm.sh/@milkdown/crepe/lib/theme/common/style.css'),
|
||||
injectStylesheet('https://esm.sh/@milkdown/crepe/lib/theme/frame/style.css')
|
||||
]);
|
||||
await ensureStylesheet('/_content/NexusReader.UI.Shared/css/vendor/milkdown-crepe.css');
|
||||
|
||||
// Dynamically import the Crepe ESM module
|
||||
const { Crepe } = await import('https://esm.sh/@milkdown/crepe');
|
||||
// Dynamically import the local JS bundle
|
||||
await import('/_content/NexusReader.UI.Shared/js/vendor/milkdown-crepe.js');
|
||||
|
||||
// Get Crepe constructor from the global window.milkdownCrepe namespace
|
||||
const Crepe = window.milkdownCrepe?.Crepe;
|
||||
if (!Crepe) {
|
||||
throw new Error("Crepe constructor not found on window.milkdownCrepe");
|
||||
}
|
||||
|
||||
// Initialize the Crepe editor instance with custom ImageBlock upload handler
|
||||
const crepe = new Crepe({
|
||||
@@ -61,7 +64,7 @@ export async function initEditor(elementId, dotNetHelper, initialMarkdown) {
|
||||
});
|
||||
|
||||
// Store the editor instance in the map
|
||||
editors.set(elementId, crepe);
|
||||
editorCache.set(elementId, crepe);
|
||||
|
||||
// Create the editor view asynchronously
|
||||
await crepe.create();
|
||||
@@ -76,7 +79,7 @@ export async function initEditor(elementId, dotNetHelper, initialMarkdown) {
|
||||
* Retrieves the current Markdown content from a specific editor instance.
|
||||
*/
|
||||
export function getMarkdownContent(elementId) {
|
||||
const crepe = editors.get(elementId);
|
||||
const crepe = editorCache.get(elementId);
|
||||
if (!crepe) {
|
||||
console.warn(`[Milkdown] No editor instance found for element: ${elementId}`);
|
||||
return "";
|
||||
@@ -88,7 +91,7 @@ export function getMarkdownContent(elementId) {
|
||||
* Safely disposes of the editor instance to prevent memory leaks in WASM.
|
||||
*/
|
||||
export async function destroyEditor(elementId) {
|
||||
const crepe = editors.get(elementId);
|
||||
const crepe = editorCache.get(elementId);
|
||||
if (crepe) {
|
||||
try {
|
||||
await crepe.destroy();
|
||||
@@ -96,6 +99,6 @@ export async function destroyEditor(elementId) {
|
||||
} catch (error) {
|
||||
console.error(`[Milkdown] Error destroying editor for element "${elementId}":`, error);
|
||||
}
|
||||
editors.delete(elementId);
|
||||
editorCache.delete(elementId);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user