mirror of
https://github.com/youfoundjk/TeXcore.git
synced 2026-07-22 07:33:31 +00:00
refactor(load-time): lazy load heavy dependencies and optimize startup performance
- Convert eager imports of multi-megabyte `pdf-lib` (via `ExportConfigModal`) and `dvi2html` (via `TikzRenderer`) to dynamic imports. - Defer `TikzRenderer` instantiation and loading to `onLayoutReady`. - Remove blocking synchronous stylesheet checks and reads of `tikzjax.css` from `TikzRenderer.onLoad()`, relying on on-demand lazy loading instead. - Implement `LazyMathSettingTab` proxy to defer evaluation of the settings UI modals and translations. - Defer `setupDOMObserver` registration to after layout is ready to avoid MutationObserver overhead during startup layout rendering. - Dynamically import `processZoteroCleanup` and `TikzEditorModal` inside their respective commands/callbacks.
This commit is contained in:
parent
1642b5cd76
commit
53def164d5
4 changed files with 80 additions and 50 deletions
|
|
@ -2,7 +2,6 @@ import { Extension, Prec, EditorState } from '@codemirror/state';
|
|||
import { EditorView, ViewPlugin, ViewUpdate } from '@codemirror/view';
|
||||
import { showNotice } from 'utils/obsidian';
|
||||
import LatexReferencer from '../../main';
|
||||
import { TikzEditorModal } from '../tikz-editor/tikz-editor-modal';
|
||||
|
||||
interface CleanableDiv extends HTMLDivElement {
|
||||
_cleanup?: () => void;
|
||||
|
|
@ -170,21 +169,24 @@ class TikzLivePreviewOverlay {
|
|||
this.plugin.isTikzEditorOpen = true;
|
||||
this.destroy();
|
||||
|
||||
new TikzEditorModal(
|
||||
this.plugin.app,
|
||||
this.plugin,
|
||||
blockRange.source,
|
||||
(newSource: string) => {
|
||||
this.view.dispatch({
|
||||
changes: {
|
||||
from: blockRange.from,
|
||||
to: blockRange.to,
|
||||
insert: newSource
|
||||
}
|
||||
});
|
||||
showNotice('TikZ block updated.');
|
||||
}
|
||||
).open();
|
||||
void (async () => {
|
||||
const { TikzEditorModal } = await import('../tikz-editor/tikz-editor-modal');
|
||||
new TikzEditorModal(
|
||||
this.plugin.app,
|
||||
this.plugin,
|
||||
blockRange.source,
|
||||
(newSource: string) => {
|
||||
this.view.dispatch({
|
||||
changes: {
|
||||
from: blockRange.from,
|
||||
to: blockRange.to,
|
||||
insert: newSource
|
||||
}
|
||||
});
|
||||
showNotice('TikZ block updated.');
|
||||
}
|
||||
).open();
|
||||
})();
|
||||
} else {
|
||||
showNotice('Please place your cursor inside a tikz block to edit.');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { TikzJaxLoader } from './tikzjax/loader';
|
|||
export class TikzRenderer {
|
||||
private loader: TikzJaxLoader;
|
||||
private tikzjaxCss: string = '';
|
||||
private isLoaded: boolean = false;
|
||||
public isLoaded: boolean = false;
|
||||
|
||||
private renderCache = new Map<string, string>();
|
||||
|
||||
|
|
@ -23,27 +23,6 @@ export class TikzRenderer {
|
|||
}
|
||||
|
||||
try {
|
||||
const adapter = this.plugin.app.vault.adapter;
|
||||
const pluginDir = this.plugin.manifest.dir;
|
||||
|
||||
if (!pluginDir) {
|
||||
throw new Error('Plugin manifest directory is not defined.');
|
||||
}
|
||||
|
||||
// Load tikzjax.css (containing base64 math fonts)
|
||||
const cssPath = `${pluginDir}/tikzjax-assets/tikzjax.css`;
|
||||
if (await adapter.exists(cssPath)) {
|
||||
this.tikzjaxCss = await adapter.read(cssPath);
|
||||
} else {
|
||||
// Try downloading it via loader
|
||||
const cssData = await this.loader.loadAssetString('tikzjax.css');
|
||||
if (cssData) {
|
||||
this.tikzjaxCss = cssData;
|
||||
} else {
|
||||
console.warn('Latex Referencer: tikzjax.css not found and download failed.');
|
||||
}
|
||||
}
|
||||
|
||||
// Inject styling for main window and pop-outs
|
||||
this.plugin.app.workspace.onLayoutReady(() => {
|
||||
this.injectCssAllWindows();
|
||||
|
|
|
|||
70
src/main.ts
70
src/main.ts
|
|
@ -1,6 +1,8 @@
|
|||
import {
|
||||
App,
|
||||
MarkdownView,
|
||||
Plugin,
|
||||
PluginSettingTab,
|
||||
TFile,
|
||||
parseLinktext,
|
||||
Menu,
|
||||
|
|
@ -13,7 +15,6 @@ import type { Extension } from '@codemirror/state';
|
|||
import { around } from 'monkey-around';
|
||||
|
||||
import { PluginSettings, DEFAULT_SETTINGS } from './settings/settings';
|
||||
import { MathSettingTab } from './settings/tab';
|
||||
|
||||
import { Provider } from './core/linker/provider-link-render';
|
||||
import { LatexLinkProvider } from './core/linker/latex-provider';
|
||||
|
|
@ -31,14 +32,11 @@ import { EquationBlock } from 'types';
|
|||
// ADDED: Import our new internal patcher function
|
||||
import { patchSuggesterWithQuickPreview } from 'ui/quick-preview/patcher';
|
||||
import { processActiveNoteEquations } from './core/equations/numbering';
|
||||
import { ExportConfigModal } from './ui/export-pdf/modal';
|
||||
import { checkAndFixCalloutMath } from 'utils/fixer';
|
||||
import { showNotice } from 'utils/obsidian';
|
||||
import { traverseFolder } from 'features/export-pdf/utils';
|
||||
import { SnippetManager } from 'features/snippets/manager';
|
||||
import { processZoteroCleanup } from 'features/zotero-cleanup';
|
||||
import { CustomNoteManager } from 'features/custom-notes/manager';
|
||||
import { TikzRenderer } from './features/tikz/renderer';
|
||||
import type { TikzRenderer } from './features/tikz/renderer';
|
||||
import {
|
||||
createRowLayoutProcessor,
|
||||
createLivePreviewRowLayoutPlugin
|
||||
|
|
@ -85,10 +83,13 @@ export default class LatexReferencer extends Plugin {
|
|||
this.customNoteManager.onLoad();
|
||||
|
||||
// TikZJax Rendering
|
||||
this.tikzRenderer = new TikzRenderer(this);
|
||||
await this.tikzRenderer.onLoad();
|
||||
this.app.workspace.onLayoutReady(async () => {
|
||||
if (this.settings.enableTikzjax) {
|
||||
await this.initTikzRenderer();
|
||||
}
|
||||
});
|
||||
|
||||
this.addSettingTab(new MathSettingTab(this.app, this));
|
||||
this.addSettingTab(new LazyMathSettingTab(this.app, this));
|
||||
|
||||
// Commands
|
||||
this.registerZoteroCommand();
|
||||
|
|
@ -134,7 +135,10 @@ export default class LatexReferencer extends Plugin {
|
|||
if (checking) {
|
||||
return true;
|
||||
}
|
||||
new ExportConfigModal(this, file).open();
|
||||
void (async () => {
|
||||
const { ExportConfigModal } = await import('./ui/export-pdf/modal');
|
||||
new ExportConfigModal(this, file).open();
|
||||
})();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -158,6 +162,7 @@ export default class LatexReferencer extends Plugin {
|
|||
.setIcon('download')
|
||||
.setSection('action')
|
||||
.onClick(async () => {
|
||||
const { ExportConfigModal } = await import('./ui/export-pdf/modal');
|
||||
new ExportConfigModal(this, file).open();
|
||||
});
|
||||
});
|
||||
|
|
@ -183,6 +188,7 @@ export default class LatexReferencer extends Plugin {
|
|||
.setTitle('Export each file to pdf')
|
||||
.setIcon('lucide-file-stack')
|
||||
.onClick(async () => {
|
||||
const { ExportConfigModal } = await import('./ui/export-pdf/modal');
|
||||
new ExportConfigModal(this, file, true).open();
|
||||
})
|
||||
);
|
||||
|
|
@ -227,11 +233,15 @@ export default class LatexReferencer extends Plugin {
|
|||
});
|
||||
|
||||
this.patchPagePreview();
|
||||
this.register(setupDOMObserver(this));
|
||||
this.app.workspace.onLayoutReady(() => {
|
||||
this.register(setupDOMObserver(this));
|
||||
});
|
||||
}
|
||||
|
||||
onunload() {
|
||||
this.tikzRenderer.onUnload();
|
||||
if (this.tikzRenderer) {
|
||||
this.tikzRenderer.onUnload();
|
||||
}
|
||||
}
|
||||
|
||||
async loadSettings() {
|
||||
|
|
@ -362,7 +372,10 @@ export default class LatexReferencer extends Plugin {
|
|||
name: 'Remove duplicate Zotero annotations',
|
||||
editorCallback: (editor: Editor, ctx: MarkdownView | MarkdownFileInfo) => {
|
||||
if (ctx instanceof MarkdownView) {
|
||||
void processZoteroCleanup(this, ctx);
|
||||
void (async () => {
|
||||
const { processZoteroCleanup } = await import('features/zotero-cleanup');
|
||||
await processZoteroCleanup(this, ctx);
|
||||
})();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -373,6 +386,7 @@ export default class LatexReferencer extends Plugin {
|
|||
const tocPath = root.path === '/' || root.path === '.' ? '_TOC_.md' : `${root.path}/_TOC_.md`;
|
||||
let content = `---\ntoc: true\ntitle: ${root.name || 'Root'}\n---\n`;
|
||||
if (root instanceof TFolder) {
|
||||
const { traverseFolder } = await import('features/export-pdf/utils');
|
||||
const files = traverseFolder(root);
|
||||
for (const file of files) {
|
||||
if (file.name === '_TOC_.md') {
|
||||
|
|
@ -388,4 +402,36 @@ export default class LatexReferencer extends Plugin {
|
|||
await this.app.vault.create(tocPath, content);
|
||||
}
|
||||
}
|
||||
|
||||
async initTikzRenderer() {
|
||||
if (!this.tikzRenderer) {
|
||||
const { TikzRenderer } = await import('./features/tikz/renderer');
|
||||
this.tikzRenderer = new TikzRenderer(this);
|
||||
await this.tikzRenderer.onLoad();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface Displayable {
|
||||
display(): void;
|
||||
}
|
||||
|
||||
class LazyMathSettingTab extends PluginSettingTab {
|
||||
constructor(
|
||||
app: App,
|
||||
public plugin: LatexReferencer
|
||||
) {
|
||||
super(app, plugin);
|
||||
}
|
||||
display(): void {
|
||||
import('./settings/tab')
|
||||
.then(({ MathSettingTab }) => {
|
||||
const tab = new MathSettingTab(this.app, this.plugin);
|
||||
tab.containerEl = this.containerEl;
|
||||
(tab as unknown as Displayable).display();
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Failed to load settings tab:', err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -581,6 +581,9 @@ export class MathSettingTab extends PluginSettingTab {
|
|||
toggle.setValue(this.plugin.settings.enableTikzjax).onChange(async value => {
|
||||
this.plugin.settings.enableTikzjax = value;
|
||||
await this.plugin.saveSettings();
|
||||
if (value) {
|
||||
await this.plugin.initTikzRenderer();
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue