257 lines
10 KiB
JavaScript
257 lines
10 KiB
JavaScript
'use strict';
|
|
|
|
var obsidian = require('obsidian');
|
|
var child_process = require('child_process');
|
|
var path = require('path');
|
|
|
|
function _interopNamespaceDefault(e) {
|
|
var n = Object.create(null);
|
|
if (e) {
|
|
Object.keys(e).forEach(function (k) {
|
|
if (k !== 'default') {
|
|
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
Object.defineProperty(n, k, d.get ? d : {
|
|
enumerable: true,
|
|
get: function () { return e[k]; }
|
|
});
|
|
}
|
|
});
|
|
}
|
|
n.default = e;
|
|
return Object.freeze(n);
|
|
}
|
|
|
|
var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
|
|
|
|
const DEFAULT_SETTINGS = {
|
|
quartoPath: 'quarto',
|
|
enableQmdLinking: true,
|
|
quartoTypst: '',
|
|
emitCompilationLogs: true, // Default is to emit logs
|
|
};
|
|
class QmdAsMdPlugin extends obsidian.Plugin {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.activePreviewProcesses = new Map();
|
|
}
|
|
async onload() {
|
|
console.log('Plugin is loading...');
|
|
try {
|
|
await this.loadSettings();
|
|
console.log('Settings loaded:', this.settings);
|
|
if (this.settings.enableQmdLinking) {
|
|
this.registerQmdExtension();
|
|
}
|
|
this.addSettingTab(new QmdSettingTab(this.app, this));
|
|
console.log('Settings tab added successfully');
|
|
this.addRibbonIcon('eye', 'Toggle Quarto Preview', async () => {
|
|
const activeView = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
|
|
if (activeView?.file && this.isQuartoFile(activeView.file)) {
|
|
console.log(`Toggling preview for: ${activeView.file.path}`);
|
|
await this.togglePreview(activeView.file);
|
|
}
|
|
else {
|
|
new obsidian.Notice('Current file is not a Quarto document');
|
|
}
|
|
});
|
|
console.log('Ribbon icon added');
|
|
this.addCommand({
|
|
id: 'toggle-quarto-preview',
|
|
name: 'Toggle Quarto Preview',
|
|
callback: async () => {
|
|
const activeView = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
|
|
if (activeView?.file && this.isQuartoFile(activeView.file)) {
|
|
console.log(`Command: Toggling preview for ${activeView.file.path}`);
|
|
await this.togglePreview(activeView.file);
|
|
}
|
|
else {
|
|
new obsidian.Notice('Current file is not a Quarto document');
|
|
}
|
|
},
|
|
hotkeys: [{ modifiers: ['Ctrl', 'Shift'], key: 'p' }],
|
|
});
|
|
console.log('Commands added');
|
|
}
|
|
catch (error) {
|
|
console.error('Error loading plugin:', error);
|
|
new obsidian.Notice('Failed to load QmdAsMdPlugin. Check the developer console for details.');
|
|
}
|
|
}
|
|
onunload() {
|
|
console.log('Plugin is unloading...');
|
|
this.stopAllPreviews();
|
|
}
|
|
async loadSettings() {
|
|
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
|
}
|
|
async saveSettings() {
|
|
await this.saveData(this.settings);
|
|
}
|
|
isQuartoFile(file) {
|
|
return file.extension === 'qmd';
|
|
}
|
|
registerQmdExtension() {
|
|
console.log('Registering .qmd as markdown...');
|
|
this.registerExtensions(['qmd'], 'markdown');
|
|
console.log('.qmd registered as markdown');
|
|
}
|
|
async togglePreview(file) {
|
|
if (this.activePreviewProcesses.has(file.path)) {
|
|
await this.stopPreview(file);
|
|
}
|
|
else {
|
|
await this.startPreview(file);
|
|
}
|
|
}
|
|
async startPreview(file) {
|
|
if (this.activePreviewProcesses.has(file.path)) {
|
|
console.log(`Preview already running for: ${file.path}`);
|
|
return; // Preview already running
|
|
}
|
|
try {
|
|
const abstractFile = this.app.vault.getAbstractFileByPath(file.path);
|
|
if (!abstractFile || !(abstractFile instanceof obsidian.TFile)) {
|
|
new obsidian.Notice(`File ${file.path} not found`);
|
|
return;
|
|
}
|
|
const filePath = this.app.vault.adapter.getFullPath(abstractFile.path);
|
|
const workingDir = path__namespace.dirname(filePath);
|
|
console.log(`Resolved file path: ${filePath}`);
|
|
console.log(`Working directory: ${workingDir}`);
|
|
const envVars = {
|
|
...process.env,
|
|
};
|
|
if (this.settings.quartoTypst.trim()) {
|
|
envVars.QUARTO_TYPST = this.settings.quartoTypst.trim();
|
|
console.log(`QUARTO_TYPST set to: ${envVars.QUARTO_TYPST}`);
|
|
}
|
|
const quartoProcess = child_process.spawn(this.settings.quartoPath, ['preview', filePath], {
|
|
cwd: workingDir,
|
|
env: envVars,
|
|
});
|
|
let previewUrl = null;
|
|
quartoProcess.stdout?.on('data', (data) => {
|
|
const output = data.toString();
|
|
if (this.settings.emitCompilationLogs) {
|
|
console.log(`Quarto Preview Output: ${output}`);
|
|
}
|
|
if (output.includes('Browse at')) {
|
|
const match = output.match(/Browse at\s+(http:\/\/[^\s]+)/);
|
|
if (match && match[1]) {
|
|
previewUrl = match[1];
|
|
new obsidian.Notice(`Preview available at ${previewUrl}`);
|
|
const leaf = this.app.workspace.getLeaf('tab');
|
|
leaf.setViewState({
|
|
type: 'webviewer',
|
|
active: true,
|
|
state: {
|
|
url: previewUrl,
|
|
},
|
|
});
|
|
this.app.workspace.revealLeaf(leaf);
|
|
}
|
|
}
|
|
});
|
|
quartoProcess.stderr?.on('data', (data) => {
|
|
if (this.settings.emitCompilationLogs) {
|
|
console.error(`Quarto Preview Error: ${data}`);
|
|
}
|
|
});
|
|
quartoProcess.on('close', (code) => {
|
|
if (code !== null && code !== 0) {
|
|
new obsidian.Notice(`Quarto preview process exited with code ${code}`);
|
|
}
|
|
this.activePreviewProcesses.delete(file.path);
|
|
});
|
|
this.activePreviewProcesses.set(file.path, quartoProcess);
|
|
new obsidian.Notice('Quarto preview started');
|
|
}
|
|
catch (error) {
|
|
console.error('Failed to start Quarto preview:', error);
|
|
new obsidian.Notice('Failed to start Quarto preview');
|
|
}
|
|
}
|
|
async stopPreview(file) {
|
|
const quartoProcess = this.activePreviewProcesses.get(file.path);
|
|
if (quartoProcess) {
|
|
if (!quartoProcess.killed) {
|
|
quartoProcess.kill();
|
|
}
|
|
this.activePreviewProcesses.delete(file.path);
|
|
new obsidian.Notice('Quarto preview stopped');
|
|
}
|
|
}
|
|
stopAllPreviews() {
|
|
this.activePreviewProcesses.forEach((quartoProcess, filePath) => {
|
|
if (!quartoProcess.killed) {
|
|
quartoProcess.kill();
|
|
}
|
|
this.activePreviewProcesses.delete(filePath);
|
|
});
|
|
if (this.activePreviewProcesses.size > 0) {
|
|
new obsidian.Notice('All Quarto previews stopped');
|
|
}
|
|
}
|
|
}
|
|
class QmdSettingTab extends obsidian.PluginSettingTab {
|
|
constructor(app, plugin) {
|
|
super(app, plugin);
|
|
this.plugin = plugin;
|
|
}
|
|
display() {
|
|
const { containerEl } = this;
|
|
containerEl.empty();
|
|
console.log('Rendering settings tab...');
|
|
containerEl.createEl('h2', { text: 'Quarto Preview Settings' });
|
|
new obsidian.Setting(containerEl)
|
|
.setName('Quarto Path')
|
|
.setDesc('Path to Quarto executable (e.g., quarto, /usr/local/bin/quarto)')
|
|
.addText((text) => text
|
|
.setPlaceholder('quarto')
|
|
.setValue(this.plugin.settings.quartoPath)
|
|
.onChange(async (value) => {
|
|
console.log(`Quarto path changed to: ${value}`);
|
|
this.plugin.settings.quartoPath = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new obsidian.Setting(containerEl)
|
|
.setName('Enable Editing Quarto Files')
|
|
.setDesc('By default, plugin allows editing .qmd files. Disable this feature if there is a conflict with .qmd editing enabled by another plugin')
|
|
.addToggle((toggle) => toggle
|
|
.setValue(this.plugin.settings.enableQmdLinking)
|
|
.onChange(async (value) => {
|
|
console.log(`Enable QMD Editing setting changed to: ${value}`);
|
|
this.plugin.settings.enableQmdLinking = value;
|
|
if (value) {
|
|
this.plugin.registerQmdExtension();
|
|
}
|
|
}));
|
|
new obsidian.Setting(containerEl)
|
|
.setName('QUARTO_TYPST Variable')
|
|
.setDesc('Define the QUARTO_TYPST environment variable (leave empty to unset)')
|
|
.addText((text) => text
|
|
.setPlaceholder('e.g., typst_path')
|
|
.setValue(this.plugin.settings.quartoTypst)
|
|
.onChange(async (value) => {
|
|
console.log(`QUARTO_TYPST set to: ${value}`);
|
|
this.plugin.settings.quartoTypst = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
new obsidian.Setting(containerEl)
|
|
.setName('Emit Compilation Logs')
|
|
.setDesc('Toggle whether to emit detailed compilation logs in the console')
|
|
.addToggle((toggle) => toggle
|
|
.setValue(this.plugin.settings.emitCompilationLogs)
|
|
.onChange(async (value) => {
|
|
console.log(`Emit Compilation Logs set to: ${value}`);
|
|
this.plugin.settings.emitCompilationLogs = value;
|
|
await this.plugin.saveSettings();
|
|
}));
|
|
console.log('Settings tab rendered successfully');
|
|
}
|
|
}
|
|
|
|
module.exports = QmdAsMdPlugin;
|
|
|
|
|
|
/* nosourcemap */ |