mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-21 09:38:01 +02:00
77 lines
2.4 KiB
TypeScript
77 lines
2.4 KiB
TypeScript
|
import { RenderResultPluginAsset } from '@joplin/renderer/types';
|
||
|
|
||
|
type PluginAssetRecord = {
|
||
|
element: HTMLElement;
|
||
|
};
|
||
|
const pluginAssetsAdded_: Record<string, PluginAssetRecord> = {};
|
||
|
|
||
|
// Note that this function keeps track of what's been added so as not to
|
||
|
// add the same CSS files multiple times.
|
||
|
//
|
||
|
// Shared with app-desktop/gui-note-viewer.
|
||
|
//
|
||
|
// TODO: If possible, refactor such that this function is not duplicated.
|
||
|
const addPluginAssets = (assets: RenderResultPluginAsset[]) => {
|
||
|
if (!assets) return;
|
||
|
|
||
|
const pluginAssetsContainer = document.getElementById('joplin-container-pluginAssetsContainer');
|
||
|
|
||
|
const processedAssetIds = [];
|
||
|
|
||
|
for (let i = 0; i < assets.length; i++) {
|
||
|
const asset = assets[i];
|
||
|
|
||
|
// # and ? can be used in valid paths and shouldn't be treated as the start of a query or fragment
|
||
|
const encodedPath = asset.path
|
||
|
.replace(/#/g, '%23')
|
||
|
.replace(/\?/g, '%3F');
|
||
|
|
||
|
const assetId = asset.name ? asset.name : encodedPath;
|
||
|
|
||
|
processedAssetIds.push(assetId);
|
||
|
|
||
|
if (pluginAssetsAdded_[assetId]) continue;
|
||
|
|
||
|
let element = null;
|
||
|
|
||
|
if (asset.mime === 'application/javascript') {
|
||
|
element = document.createElement('script');
|
||
|
element.src = encodedPath;
|
||
|
pluginAssetsContainer.appendChild(element);
|
||
|
} else if (asset.mime === 'text/css') {
|
||
|
element = document.createElement('link');
|
||
|
element.rel = 'stylesheet';
|
||
|
element.href = encodedPath;
|
||
|
pluginAssetsContainer.appendChild(element);
|
||
|
}
|
||
|
|
||
|
pluginAssetsAdded_[assetId] = {
|
||
|
element,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
// Once we have added the relevant assets, we also remove those that
|
||
|
// are no longer needed. It's necessary in particular for the CSS
|
||
|
// generated by noteStyle - if we don't remove it, we might end up
|
||
|
// with two or more stylesheet and that will create conflicts.
|
||
|
//
|
||
|
// It was happening for example when automatically switching from
|
||
|
// light to dark theme, and then back to light theme - in that case
|
||
|
// the viewer would remain dark because it would use the dark
|
||
|
// stylesheet that would still be in the DOM.
|
||
|
for (const [assetId, asset] of Object.entries(pluginAssetsAdded_)) {
|
||
|
if (!processedAssetIds.includes(assetId)) {
|
||
|
try {
|
||
|
asset.element.remove();
|
||
|
} catch (error) {
|
||
|
// We don't throw an exception but we log it since
|
||
|
// it shouldn't happen
|
||
|
console.warn('Tried to remove an asset but got an error', error);
|
||
|
}
|
||
|
pluginAssetsAdded_[assetId] = null;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
export default addPluginAssets;
|