mirror of
https://github.com/ryojerryyu/obsidian-jessiecode.git
synced 2026-07-22 06:43:22 +00:00
175 lines
5 KiB
TypeScript
175 lines
5 KiB
TypeScript
import { loadMathJax, MarkdownView, Plugin } from 'obsidian';
|
|
import { JSXGraph } from 'jsxgraph';
|
|
import { renderError } from 'src/error';
|
|
import { Graph, GraphBuilder, GraphInfo } from 'src/types';
|
|
import './src/theme/obsidian.ts';
|
|
import {
|
|
DEFAULT_SETTINGS,
|
|
GraphsSettings as GraphsSettings,
|
|
GraphsSettingsTab,
|
|
} from 'src/settings';
|
|
import { ExportModal } from 'src/exportModal';
|
|
import { GraphBuilderJessieCode } from 'src/graphBuilderJessieCode.js';
|
|
|
|
export default class ObsidianJessieCode extends Plugin {
|
|
settings: GraphsSettings;
|
|
count = 0;
|
|
graphs: Map<string, Graph[]> = new Map();
|
|
|
|
async onload() {
|
|
await this.loadSettings();
|
|
|
|
this.addSettingTab(new GraphsSettingsTab(this.app, this));
|
|
|
|
await loadMathJax();
|
|
|
|
//@ts-ignore
|
|
if (typeof MathJax !== 'undefined') {
|
|
//@ts-ignore
|
|
MathJax.config.tex.inlineMath = [['$', '$']];
|
|
//@ts-ignore
|
|
MathJax.config.tex.processEscapes = true;
|
|
//@ts-ignore
|
|
MathJax.config.chtml.adaptiveCSS = false;
|
|
//@ts-ignore
|
|
await MathJax.startup.getComponents();
|
|
}
|
|
|
|
// remove unused boards when opening a new file
|
|
this.app.workspace.on('file-open', () => {
|
|
this.cullBoards();
|
|
});
|
|
|
|
// remove unused boards when opening closing a window
|
|
this.app.workspace.on('window-close', () => {
|
|
this.cullBoards();
|
|
});
|
|
|
|
this.addCommand({
|
|
id: 'export-graphs',
|
|
name: 'Export graphs',
|
|
checkCallback: (checking: boolean) => {
|
|
const view = this.app.workspace.getActiveViewOfType(MarkdownView)?.getMode();
|
|
// only have the command available while in read mode
|
|
if (view === 'preview') {
|
|
if (!checking) {
|
|
const graphs = [];
|
|
const activeGraphs = this.graphs.get(this.getCurrentFileName()) ?? [];
|
|
|
|
for (const graph of activeGraphs) {
|
|
const div: HTMLElement = graph.board.containerObj;
|
|
|
|
// check if board is from read mode or live preview
|
|
if (!div.hasClass('LivePreview')) {
|
|
graphs.push(graph.board);
|
|
}
|
|
}
|
|
new ExportModal(this, graphs).open();
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
});
|
|
|
|
this.registerMarkdownCodeBlockProcessor('jessiecode', (source, element) => {
|
|
this.handleCodeBlock(
|
|
source,
|
|
element,
|
|
new GraphBuilderJessieCode(this.settings.height, this.settings.width),
|
|
);
|
|
});
|
|
}
|
|
|
|
handleCodeBlock(source: string, element: HTMLElement, graphBuilder: GraphBuilder) {
|
|
try {
|
|
graphBuilder.parseCodeBlock(source);
|
|
} catch (e) {
|
|
renderError(e, element);
|
|
return;
|
|
}
|
|
|
|
const currentFileName = this.getCurrentFileName();
|
|
|
|
// create the div that contains the board
|
|
const graphDiv = element.createEl('div', { cls: 'jxgbox' });
|
|
|
|
if (this.app.workspace.getActiveViewOfType(MarkdownView)?.getMode() === 'source') {
|
|
graphDiv.addClass('LivePreview');
|
|
}
|
|
|
|
graphDiv.id = 'graph' + this.count;
|
|
this.count++;
|
|
|
|
let graph: Graph;
|
|
try {
|
|
// create the board
|
|
graph = graphBuilder.createBoard(graphDiv);
|
|
} catch (e) {
|
|
renderError(e, element);
|
|
return;
|
|
}
|
|
|
|
// add graph to map based on file name
|
|
if (this.graphs.has(currentFileName)) {
|
|
this.graphs.get(currentFileName)?.push(graph);
|
|
} else {
|
|
this.graphs.set(currentFileName, [graph]);
|
|
}
|
|
}
|
|
|
|
onunload() {
|
|
// remove all of the graphs
|
|
for (const key of this.graphs.keys()) {
|
|
const graphs: Graph[] = this.graphs.get(key) ?? [];
|
|
|
|
for (const graph of graphs) {
|
|
JSXGraph.freeBoard(graph.board);
|
|
graph.board.containerObj.remove();
|
|
}
|
|
this.graphs.delete(key);
|
|
}
|
|
}
|
|
|
|
async loadSettings() {
|
|
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
|
|
|
// set the css variables
|
|
document.documentElement.style.setProperty('--graph-height', this.settings.height + 'px');
|
|
document.documentElement.style.setProperty('--graph-width', this.settings.width + 'px');
|
|
document.documentElement.style.setProperty('--graph-alignment', this.settings.alignment);
|
|
}
|
|
|
|
async saveSettings() {
|
|
await this.saveData(this.settings);
|
|
}
|
|
|
|
getCurrentFileName(): string {
|
|
let currentFileName = '';
|
|
const currentFile = this.app.workspace.getActiveFile();
|
|
if (currentFile) {
|
|
currentFileName = currentFile.basename.replace(/\s/g, '');
|
|
}
|
|
return currentFileName;
|
|
}
|
|
|
|
cullBoards() {
|
|
// get the active files
|
|
const activeFileNames: string[] = [];
|
|
const files = this.app.workspace.getLeavesOfType('markdown');
|
|
files.forEach((file) => activeFileNames.push(file.getDisplayText().replace(/\s/g, '')));
|
|
|
|
// if the graph is not in an active file remove it
|
|
for (const key of this.graphs.keys()) {
|
|
if (!activeFileNames.contains(key)) {
|
|
const graphs: Graph[] = this.graphs.get(key) ?? [];
|
|
|
|
for (const graph of graphs) {
|
|
JSXGraph.freeBoard(graph.board);
|
|
graph.board.containerObj.remove();
|
|
}
|
|
this.graphs.delete(key);
|
|
}
|
|
}
|
|
}
|
|
}
|