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)
|
// 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
|
* Asynchronously injects a stylesheet link tag into the document head
|
||||||
* and returns a Promise that resolves when the stylesheet is fully loaded.
|
* and returns a Promise that resolves when the stylesheet is fully loaded.
|
||||||
*/
|
*/
|
||||||
async function injectStylesheet(url) {
|
async function ensureStylesheet(href) {
|
||||||
if (document.querySelector(`link[href="${url}"]`)) {
|
if (document.querySelector(`link[href="${href}"]`)) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const link = document.createElement('link');
|
const link = document.createElement('link');
|
||||||
link.rel = 'stylesheet';
|
link.rel = 'stylesheet';
|
||||||
link.href = url;
|
link.href = href;
|
||||||
link.onload = () => resolve();
|
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);
|
document.head.appendChild(link);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -31,13 +31,16 @@ export async function initEditor(elementId, dotNetHelper, initialMarkdown) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Condition 2: Prevent FOUC by loading stylesheets before instantiating the editor
|
// Condition 2: Prevent FOUC by loading stylesheets before instantiating the editor
|
||||||
await Promise.all([
|
await ensureStylesheet('/_content/NexusReader.UI.Shared/css/vendor/milkdown-crepe.css');
|
||||||
injectStylesheet('https://esm.sh/@milkdown/crepe/lib/theme/common/style.css'),
|
|
||||||
injectStylesheet('https://esm.sh/@milkdown/crepe/lib/theme/frame/style.css')
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Dynamically import the Crepe ESM module
|
// Dynamically import the local JS bundle
|
||||||
const { Crepe } = await import('https://esm.sh/@milkdown/crepe');
|
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
|
// Initialize the Crepe editor instance with custom ImageBlock upload handler
|
||||||
const crepe = new Crepe({
|
const crepe = new Crepe({
|
||||||
@@ -61,7 +64,7 @@ export async function initEditor(elementId, dotNetHelper, initialMarkdown) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Store the editor instance in the map
|
// Store the editor instance in the map
|
||||||
editors.set(elementId, crepe);
|
editorCache.set(elementId, crepe);
|
||||||
|
|
||||||
// Create the editor view asynchronously
|
// Create the editor view asynchronously
|
||||||
await crepe.create();
|
await crepe.create();
|
||||||
@@ -76,7 +79,7 @@ export async function initEditor(elementId, dotNetHelper, initialMarkdown) {
|
|||||||
* Retrieves the current Markdown content from a specific editor instance.
|
* Retrieves the current Markdown content from a specific editor instance.
|
||||||
*/
|
*/
|
||||||
export function getMarkdownContent(elementId) {
|
export function getMarkdownContent(elementId) {
|
||||||
const crepe = editors.get(elementId);
|
const crepe = editorCache.get(elementId);
|
||||||
if (!crepe) {
|
if (!crepe) {
|
||||||
console.warn(`[Milkdown] No editor instance found for element: ${elementId}`);
|
console.warn(`[Milkdown] No editor instance found for element: ${elementId}`);
|
||||||
return "";
|
return "";
|
||||||
@@ -88,7 +91,7 @@ export function getMarkdownContent(elementId) {
|
|||||||
* Safely disposes of the editor instance to prevent memory leaks in WASM.
|
* Safely disposes of the editor instance to prevent memory leaks in WASM.
|
||||||
*/
|
*/
|
||||||
export async function destroyEditor(elementId) {
|
export async function destroyEditor(elementId) {
|
||||||
const crepe = editors.get(elementId);
|
const crepe = editorCache.get(elementId);
|
||||||
if (crepe) {
|
if (crepe) {
|
||||||
try {
|
try {
|
||||||
await crepe.destroy();
|
await crepe.destroy();
|
||||||
@@ -96,6 +99,6 @@ export async function destroyEditor(elementId) {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`[Milkdown] Error destroying editor for element "${elementId}":`, 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