881 lines
29 KiB
JavaScript
881 lines
29 KiB
JavaScript
/*
|
|
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
|
if you want to view the source, please visit the github repository of this plugin
|
|
*/
|
|
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
|
|
// src/main.ts
|
|
var main_exports = {};
|
|
__export(main_exports, {
|
|
default: () => MathematicaPlot
|
|
});
|
|
module.exports = __toCommonJS(main_exports);
|
|
|
|
// src/modal/menus/graph/helpers.ts
|
|
var import_obsidian = require("obsidian");
|
|
var renderOptions = (optionsFields) => (el, settings, options) => {
|
|
el.createEl("h5", {
|
|
text: `Plot Options ${settings.raster.dim}`
|
|
});
|
|
Object.entries(optionsFields).forEach(
|
|
(entry, index) => new import_obsidian.Setting(index === 0 ? el : el.createDiv()).setName(entry[1].name).setDesc(entry[1].desc).addText(
|
|
(component) => component.setValue(options[entry[0]] || "").onChange((value) => {
|
|
options[entry[0]] = value;
|
|
})
|
|
)
|
|
);
|
|
new import_obsidian.Setting(el.createDiv()).setName("Others").setDesc(
|
|
"Add any other option for the plot following the mathematica syntax. For example: ClippingStyle -> Red, ScalingFunctions -> Reverse"
|
|
).addTextArea(
|
|
(component) => component.setValue(options.others || "").onChange((value) => {
|
|
options.others = value;
|
|
})
|
|
);
|
|
};
|
|
var renderIntervalForm = (el, variable, interval, desc = { min: "", max: "" }) => {
|
|
new import_obsidian.Setting(el.createDiv()).setName(`${variable} min`).setDesc(desc.min).addText(
|
|
(component) => component.setValue(interval.min).onChange((value) => {
|
|
interval.min = value;
|
|
})
|
|
);
|
|
new import_obsidian.Setting(el.createDiv()).setName(`${variable} max`).setDesc(desc.max).addText(
|
|
(component) => component.setValue(interval.max).onChange((value) => {
|
|
interval.max = value;
|
|
})
|
|
);
|
|
};
|
|
var defaultGraphType = () => ({
|
|
plot: {
|
|
expression: "",
|
|
plotRange: { x: { min: "", max: "" }, y: { min: "", max: "" } }
|
|
},
|
|
parametricPlot: {
|
|
components: [],
|
|
type: "curve",
|
|
domain: { u: { min: "", max: "" }, v: { min: "", max: "" } }
|
|
},
|
|
regionPlot: {
|
|
expression: "",
|
|
domain: {
|
|
x: { min: "", max: "" },
|
|
y: { min: "", max: "" },
|
|
z: { min: "", max: "" }
|
|
}
|
|
},
|
|
contourPlot: {
|
|
expression: "",
|
|
domain: {
|
|
x: { min: "", max: "" },
|
|
y: { min: "", max: "" },
|
|
z: { min: "", max: "" }
|
|
}
|
|
},
|
|
vectorPlot: {
|
|
components: [],
|
|
domain: {
|
|
x: { min: "", max: "" },
|
|
y: { min: "", max: "" },
|
|
z: { min: "", max: "" }
|
|
}
|
|
}
|
|
});
|
|
var defaultGraph = (id, type) => ({
|
|
id,
|
|
type,
|
|
options: {},
|
|
...defaultGraphType()
|
|
});
|
|
var graphTypesOptions = {
|
|
plot: "Plot",
|
|
parametricPlot: "Parametric Plot",
|
|
regionPlot: "Region Plot",
|
|
contourPlot: "Contour Plot",
|
|
vectorPlot: "Vector Plot"
|
|
};
|
|
var graphTypeDescription = {
|
|
plot: "Scalar functions",
|
|
parametricPlot: "Curves or Surfaces given in parametric form",
|
|
regionPlot: "Regions defined by inequalities",
|
|
contourPlot: "Contour plot for level sets",
|
|
vectorPlot: "Plot vectors from a vector field function"
|
|
};
|
|
|
|
// src/main.ts
|
|
var import_obsidian11 = require("obsidian");
|
|
|
|
// src/modal/menus/general.ts
|
|
var import_obsidian2 = require("obsidian");
|
|
var generalSettings = {
|
|
axes: {
|
|
desc: "Whether to draw axes",
|
|
name: "Axes"
|
|
},
|
|
axesLabel: {
|
|
desc: "",
|
|
name: "Axes Label"
|
|
},
|
|
plotLabel: {
|
|
name: "Label",
|
|
desc: "Overall label for the plot"
|
|
},
|
|
frame: {
|
|
desc: "Whether to put a frame around the plot",
|
|
name: "Frame"
|
|
},
|
|
frameLabel: {
|
|
name: "Frame Label"
|
|
},
|
|
boxed: {
|
|
desc: "Whether to draw the bounding box for 3d graphics",
|
|
name: "Boxed"
|
|
}
|
|
};
|
|
var renderGeneralSettings = (el, modal) => {
|
|
const settings = modal.settings;
|
|
el.createEl("h5", { text: "General settings" });
|
|
Object.entries(generalSettings).forEach(
|
|
(setting, index) => {
|
|
const fieldName = setting[0];
|
|
const value = setting[1];
|
|
const elToDisplay = index == 0 ? el : el.createDiv();
|
|
new import_obsidian2.Setting(elToDisplay).addText(
|
|
(text) => text.setValue(settings.general[fieldName] || "").onChange(
|
|
(value2) => settings.general[fieldName] = value2
|
|
)
|
|
).setName(value.name).setDesc(value.desc || "");
|
|
}
|
|
);
|
|
};
|
|
|
|
// src/utils/plot.ts
|
|
var import_util = require("util");
|
|
var import_child_process = require("child_process");
|
|
|
|
// src/utils/parsers.ts
|
|
var mathematicaOptionsParser = {
|
|
plotLabels: (value) => `PlotLabels -> ${value}`,
|
|
plotStyle: (value) => `PlotStyle -> ${value}`,
|
|
filling: (value) => `Filling -> ${value}`,
|
|
fillingStyle: (value) => `FillingStyle -> ${value}`,
|
|
boxed: (value) => `Boxed -> ${value}`,
|
|
boundaryStyle: (value) => `BoundaryStyle -> ${value}`,
|
|
axes: (value) => `Axes -> ${value}`,
|
|
axesLabel: (value) => `AxesLabel -> ${value}`,
|
|
frame: (value) => `Frame -> ${value}`,
|
|
frameLabel: (value) => `FrameLabel -> ${value}`,
|
|
plotLegends: (value) => `PlotLegends -> ${value}`,
|
|
plotLabel: (value) => `PlotLabel -> ${value}`,
|
|
others: (value) => value
|
|
};
|
|
var parseOptions = (options) => {
|
|
const opts = Object.entries(options).filter((opt) => opt[1]).map(
|
|
(opt) => mathematicaOptionsParser[opt[0]](opt[1])
|
|
).join();
|
|
if (!opts)
|
|
return "";
|
|
else
|
|
return `,${opts}`;
|
|
};
|
|
var mathematicaPlotParser2D = {
|
|
parametricPlot: (parametricPlot, opts) => {
|
|
const {
|
|
components,
|
|
domain: { u }
|
|
} = parametricPlot;
|
|
const options = parseOptions(opts);
|
|
return `ParametricPlot[{${[
|
|
components[0],
|
|
components[1]
|
|
].join()}}, {u, ${u.min}, ${u.max}} ${options}]`;
|
|
},
|
|
plot: (plot, opts) => {
|
|
const { expression, plotRange } = plot;
|
|
const options = parseOptions(opts);
|
|
return `Plot[${expression}, {x, ${plotRange.x.min}, ${plotRange.x.max}} ${options}]`;
|
|
},
|
|
regionPlot: (regionPlot, opts) => {
|
|
const {
|
|
expression,
|
|
domain: { x, y }
|
|
} = regionPlot;
|
|
const options = parseOptions(opts);
|
|
return `RegionPlot[${expression}, {x, ${x.min}, ${x.max}}, {y, ${y.min}, ${y.max}} ${options}]`;
|
|
},
|
|
contourPlot: (contourPlot, opts) => {
|
|
const {
|
|
expression,
|
|
domain: { x, y }
|
|
} = contourPlot;
|
|
const options = parseOptions(opts);
|
|
return `ContourPlot[${expression}, {x, ${x.min}, ${x.max}}, {y, ${y.min}, ${y.max}} ${options}]`;
|
|
},
|
|
vectorPlot: (vectorPlot, opts) => {
|
|
const { components, domain } = vectorPlot;
|
|
const { x, y } = domain;
|
|
const options = parseOptions(opts);
|
|
return `VectorPlot[{${[components[0], components[1]].join()}}, {x, ${x.min}, ${x.max}}, {y, ${y.min}, ${y.max}} ${options}]`;
|
|
}
|
|
};
|
|
var mathematicaPlotParser3D = {
|
|
parametricPlot: (parametricPlot, opts) => {
|
|
const {
|
|
components,
|
|
domain: { u, v },
|
|
type
|
|
} = parametricPlot;
|
|
const options = parseOptions(opts);
|
|
const base = (v2) => `ParametricPlot3D[{${components.join()}}, {u, ${u.min}, ${u.max}} ${v2} ${options}]`;
|
|
if (type === "surface")
|
|
return base(`, {v, ${v.min}, ${v.max}}`);
|
|
return base("");
|
|
},
|
|
plot: (plot, opts) => {
|
|
const { expression, plotRange } = plot;
|
|
const options = parseOptions(opts);
|
|
return `Plot3D[${expression}, {x, ${plotRange.x.min}, ${plotRange.x.max}}, {y, ${plotRange.y.min}, ${plotRange.y.max}} ${options}]`;
|
|
},
|
|
regionPlot: (regionPlot, opts) => {
|
|
const {
|
|
expression,
|
|
domain: { x, y, z }
|
|
} = regionPlot;
|
|
const options = parseOptions(opts);
|
|
return `RegionPlot3D[${expression}, {x, ${x.min}, ${x.max}}, {y, ${y.min}, ${y.max}}, {z, ${z.min}, ${z.max}} ${options}]`;
|
|
},
|
|
contourPlot: (contourPlot, opts) => {
|
|
const {
|
|
expression,
|
|
domain: { x, y, z }
|
|
} = contourPlot;
|
|
const options = parseOptions(opts);
|
|
return `ContourPlot3D[${expression}, {x, ${x.min}, ${x.max}}, {y, ${y.min}, ${y.max}}, {z, ${z.min}, ${z.max}} ${options}]`;
|
|
},
|
|
vectorPlot: (vectorPlot, opts) => {
|
|
const { components, domain } = vectorPlot;
|
|
const { x, y, z } = domain;
|
|
const options = parseOptions(opts);
|
|
return `VectorPlot3D[{${components.join()}}, {x, ${x.min}, ${x.max}}, {y, ${y.min}, ${y.max}}, {z, ${z.min}, ${z.max}}${options}]`;
|
|
}
|
|
};
|
|
var rasterizeParser = (code, settings) => {
|
|
var _a, _b, _c, _d;
|
|
const generalOptions = parseOptions(settings.general);
|
|
return `Rasterize[Show[${code} ${generalOptions}], ImageSize -> {${((_b = (_a = settings.raster) == null ? void 0 : _a.size) == null ? void 0 : _b.width) || 250}, ${((_d = (_c = settings.raster) == null ? void 0 : _c.size) == null ? void 0 : _d.height) || "Automatic"}}, Background -> ${settings.raster.background}, AspectRatio -> Automatic]`;
|
|
};
|
|
var mathematicaParser2D = (settings) => {
|
|
const parsedGraphs = settings.graphs.map(
|
|
(graph) => mathematicaPlotParser2D[graph.type](graph[graph.type], graph.options)
|
|
);
|
|
return rasterizeParser(parsedGraphs.join(), settings);
|
|
};
|
|
var mathematicaParser3D = (settings) => {
|
|
const parsedGraphs = settings.graphs.map(
|
|
(graph) => mathematicaPlotParser3D[graph.type](graph[graph.type], graph.options)
|
|
);
|
|
return rasterizeParser(parsedGraphs.join(), settings);
|
|
};
|
|
|
|
// src/utils/plot.ts
|
|
var import_obsidian3 = require("obsidian");
|
|
var isValidBase64 = (str) => {
|
|
try {
|
|
window.atob(str);
|
|
return true;
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
};
|
|
var getBase64Plot = async (plot, { useCloud, wolframScriptPath }) => {
|
|
try {
|
|
const { stdout, stderr } = await (0, import_util.promisify)(import_child_process.exec)(
|
|
`${wolframScriptPath ? '"' + wolframScriptPath + '"' : "wolframscript"} ${useCloud ? "--cloud" : ""} --code "ExportString[${plot}, {\\"Base64\\", \\"PNG\\"}]"`
|
|
);
|
|
if (stderr)
|
|
return { error: stderr, base64: "" };
|
|
if (!isValidBase64(stdout))
|
|
return { error: stdout, base64: "" };
|
|
return { error: "", base64: stdout };
|
|
} catch (err) {
|
|
return { error: err, base64: "" };
|
|
}
|
|
};
|
|
var parseCodeBlock = (code) => {
|
|
try {
|
|
const settings = (0, import_obsidian3.parseYaml)(code);
|
|
let parsedCode = "";
|
|
if (settings.raster.dim == "2D")
|
|
parsedCode = mathematicaParser2D(settings);
|
|
if (settings.raster.dim == "3D")
|
|
parsedCode = mathematicaParser3D(settings);
|
|
return { code: parsedCode.replace(/\s/g, ""), error: "" };
|
|
} catch (err) {
|
|
console.log(err);
|
|
return { error: err.message, code: "" };
|
|
}
|
|
};
|
|
var buildBase64URL = (base64, format) => `data:image/${format};base64,${base64}`;
|
|
|
|
// src/graphRender.ts
|
|
var renderGraph = async (el, source, { useCloud, wolframScriptPath }) => {
|
|
el.empty();
|
|
el.textContent = "Loading...";
|
|
const { code, error: error1 } = parseCodeBlock(source);
|
|
if (error1)
|
|
return el.textContent = error1;
|
|
const { base64, error: error2 } = await getBase64Plot(code, {
|
|
useCloud,
|
|
wolframScriptPath
|
|
});
|
|
if (error2)
|
|
return el.textContent = error2;
|
|
el.empty();
|
|
const src = buildBase64URL(base64, "png");
|
|
const img = document.createElement("img");
|
|
img.src = src;
|
|
el.appendChild(img);
|
|
};
|
|
|
|
// src/modal/menus/graphPreview.ts
|
|
var renderGraphPreview = async (el, { settings, plugin }) => {
|
|
const content = el.createDiv();
|
|
const graphEl = el.createDiv();
|
|
content.createEl("h5", { text: "Graph preview" });
|
|
content.createEl("p", { text: "A preview of what your graph looks like" });
|
|
el.createEl("button", {
|
|
text: "Render preview",
|
|
attr: { style: "width: 100%;" }
|
|
}).onClickEvent((e) => {
|
|
e.preventDefault();
|
|
renderGraph(graphEl, JSON.stringify(settings), { ...plugin.settings });
|
|
});
|
|
};
|
|
|
|
// src/modal/menus/graph/settings2d.ts
|
|
var import_obsidian4 = require("obsidian");
|
|
var renderPlotSettings = (el, graph) => {
|
|
new import_obsidian4.Setting(el.createDiv()).setName("f(x) = ").setDesc("You can also provide a list of functions {f1, f2, ...}").addTextArea(
|
|
(component) => component.setValue(graph.expression).onChange((value) => {
|
|
graph.expression = value;
|
|
})
|
|
);
|
|
renderIntervalForm(el, "x", graph.plotRange.x);
|
|
};
|
|
var renderParametricPlotSettings = (el, graph) => {
|
|
new import_obsidian4.Setting(el.createDiv()).setName("g1(u) = ").addTextArea(
|
|
(component) => component.setValue(graph.components[0]).onChange((value) => {
|
|
graph.components[0] = value;
|
|
})
|
|
);
|
|
new import_obsidian4.Setting(el.createDiv()).setName("g2(u) = ").addTextArea(
|
|
(component) => component.setValue(graph.components[1]).onChange((value) => {
|
|
graph.components[1] = value;
|
|
})
|
|
);
|
|
renderIntervalForm(el, "u", graph.domain.u);
|
|
};
|
|
var renderRegionPlotSettings = (el, graph) => {
|
|
new import_obsidian4.Setting(el.createDiv()).setName("expression (x,y)").setDesc("You can also provide a list of expressions {e1, e2, ...}").addTextArea(
|
|
(component) => component.setValue(graph.expression).onChange((value) => {
|
|
graph.expression = value;
|
|
})
|
|
);
|
|
renderIntervalForm(el, "x", graph.domain.x);
|
|
renderIntervalForm(el, "y", graph.domain.y);
|
|
};
|
|
var renderContourPlotSettings = (el, graph) => {
|
|
new import_obsidian4.Setting(el.createDiv()).setName("expression (x,y)").setDesc("You can also provide a list of expressions {e1, e2, ...}").addTextArea(
|
|
(component) => component.setValue(graph.expression).onChange((value) => {
|
|
graph.expression = value;
|
|
})
|
|
);
|
|
renderIntervalForm(el, "x", graph.domain.x);
|
|
renderIntervalForm(el, "y", graph.domain.y);
|
|
};
|
|
var renderVectorPlotSettings = (el, graph) => {
|
|
new import_obsidian4.Setting(el.createDiv()).setName("Vx(x,y) = ").addTextArea(
|
|
(component) => component.setValue(graph.components[0]).onChange((value) => {
|
|
graph.components[0] = value;
|
|
})
|
|
);
|
|
new import_obsidian4.Setting(el.createDiv()).setName("Vy(x,y) = ").addTextArea(
|
|
(component) => component.setValue(graph.components[1]).onChange((value) => {
|
|
graph.components[1] = value;
|
|
})
|
|
);
|
|
renderIntervalForm(el, "x", graph.domain.x);
|
|
renderIntervalForm(el, "y", graph.domain.y);
|
|
};
|
|
var optsFields2D = {
|
|
plotLabels: {
|
|
name: "Plot Labels",
|
|
desc: "Labels to use for fields"
|
|
},
|
|
plotLegends: {
|
|
name: "Plot Legends",
|
|
desc: "Legends for fields"
|
|
},
|
|
plotStyle: {
|
|
name: "Plot Style",
|
|
desc: "Graphics directives to specify the style for each field"
|
|
},
|
|
filling: {
|
|
name: "Filling",
|
|
desc: "Filling to insert under each field"
|
|
},
|
|
fillingStyle: {
|
|
name: "Filling Style",
|
|
desc: "Style to use for filling "
|
|
}
|
|
};
|
|
var renders2D = {
|
|
renderSettings: {
|
|
plot: renderPlotSettings,
|
|
parametricPlot: renderParametricPlotSettings,
|
|
regionPlot: renderRegionPlotSettings,
|
|
contourPlot: renderContourPlotSettings,
|
|
vectorPlot: renderVectorPlotSettings
|
|
},
|
|
renderOptions: renderOptions(optsFields2D)
|
|
};
|
|
|
|
// src/modal/menus/graph/settings3d.ts
|
|
var import_obsidian5 = require("obsidian");
|
|
var renderPlotSettings2 = (el, graph) => {
|
|
new import_obsidian5.Setting(el.createDiv()).setName("f(x, y) = ").setDesc("You can also provide a list of functions {f1, f2, ...}").addTextArea(
|
|
(component) => component.setValue(graph.expression).onChange((value) => {
|
|
graph.expression = value;
|
|
})
|
|
);
|
|
renderIntervalForm(el, "x", graph.plotRange.x);
|
|
renderIntervalForm(el, "y", graph.plotRange.y);
|
|
};
|
|
var renderParametricPlotSettings2 = (el, graph) => {
|
|
const renderParametricCurveSettings = (el2) => {
|
|
new import_obsidian5.Setting(el2.createDiv()).setName("g1(u) =").addTextArea(
|
|
(component) => component.setValue(graph.components[0]).onChange((value) => {
|
|
graph.components[0] = value;
|
|
})
|
|
);
|
|
new import_obsidian5.Setting(el2.createDiv()).setName("g2(u) =").addTextArea(
|
|
(component) => component.setValue(graph.components[1]).onChange((value) => {
|
|
graph.components[1] = value;
|
|
})
|
|
);
|
|
new import_obsidian5.Setting(el2.createDiv()).setName("g3(u) =").addTextArea(
|
|
(component) => component.setValue(graph.components[2]).onChange((value) => {
|
|
graph.components[2] = value;
|
|
})
|
|
);
|
|
renderIntervalForm(el2, "u", graph.domain.u);
|
|
};
|
|
const renderParametricSurfaceSettings = (el2) => {
|
|
new import_obsidian5.Setting(el2.createDiv()).setName("g1(u, v) =").addTextArea(
|
|
(component) => component.setValue(graph.components[0]).onChange((value) => {
|
|
graph.components[0] = value;
|
|
})
|
|
);
|
|
new import_obsidian5.Setting(el2.createDiv()).setName("g2(u, v) =").addTextArea(
|
|
(component) => component.setValue(graph.components[1]).onChange((value) => {
|
|
graph.components[1] = value;
|
|
})
|
|
);
|
|
new import_obsidian5.Setting(el2.createDiv()).setName("g3(u, v) =").addTextArea(
|
|
(component) => component.setValue(graph.components[2]).onChange((value) => {
|
|
graph.components[2] = value;
|
|
})
|
|
);
|
|
renderIntervalForm(el2, "u", graph.domain.u);
|
|
renderIntervalForm(el2, "v", graph.domain.v);
|
|
};
|
|
new import_obsidian5.Setting(el.createDiv()).setName("Space").addDropdown(
|
|
(component) => component.addOptions({
|
|
curve: "Curve",
|
|
surface: "Surface"
|
|
}).setValue(graph.type).onChange((value) => {
|
|
graph.type = value;
|
|
renderSettings2();
|
|
})
|
|
);
|
|
const settingsEl = el.createDiv();
|
|
const renderSettings2 = () => {
|
|
settingsEl.empty();
|
|
if (graph.type === "curve")
|
|
renderParametricCurveSettings(settingsEl);
|
|
else
|
|
renderParametricSurfaceSettings(settingsEl);
|
|
};
|
|
renderSettings2();
|
|
};
|
|
var renderRegionPlotSettings2 = (el, graph) => {
|
|
new import_obsidian5.Setting(el.createDiv()).setName("expression (x,y,z)").setDesc("You can also provide a list of expressions {e1, e2, ...}").addTextArea(
|
|
(component) => component.setValue(graph.expression).onChange((value) => {
|
|
graph.expression = value;
|
|
})
|
|
);
|
|
renderIntervalForm(el, "x", graph.domain.x);
|
|
renderIntervalForm(el, "y", graph.domain.y);
|
|
renderIntervalForm(el, "z", graph.domain.z);
|
|
};
|
|
var renderContourPlotSettings2 = (el, graph) => {
|
|
new import_obsidian5.Setting(el.createDiv()).setName("expression (x,y,z)").setDesc("You can also provide a list of expressions {e1, e2, ...}").addTextArea(
|
|
(component) => component.setValue(graph.expression).onChange((value) => {
|
|
graph.expression = value;
|
|
})
|
|
);
|
|
renderIntervalForm(el, "x", graph.domain.x);
|
|
renderIntervalForm(el, "y", graph.domain.y);
|
|
renderIntervalForm(el, "z", graph.domain.z);
|
|
};
|
|
var renderVectorPlotSettings2 = (el, graph) => {
|
|
new import_obsidian5.Setting(el.createDiv()).setName("Vx(x,y) = ").addTextArea(
|
|
(component) => component.setValue(graph.components[0]).onChange((value) => {
|
|
graph.components[0] = value;
|
|
})
|
|
);
|
|
new import_obsidian5.Setting(el.createDiv()).setName("Vy(x,y) = ").addTextArea(
|
|
(component) => component.setValue(graph.components[1]).onChange((value) => {
|
|
graph.components[1] = value;
|
|
})
|
|
);
|
|
new import_obsidian5.Setting(el.createDiv()).setName("Vz(x,y) = ").addTextArea(
|
|
(component) => component.setValue(graph.components[2]).onChange((value) => {
|
|
graph.components[2] = value;
|
|
})
|
|
);
|
|
renderIntervalForm(el, "x", graph.domain.x);
|
|
renderIntervalForm(el, "y", graph.domain.y);
|
|
renderIntervalForm(el, "z", graph.domain.z);
|
|
};
|
|
var optsFields = {
|
|
...optsFields2D,
|
|
boundaryStyle: {
|
|
name: "Boundary Style",
|
|
desc: "How to draw boundary lines for surfaces"
|
|
}
|
|
};
|
|
var renders3D = {
|
|
renderSettings: {
|
|
plot: renderPlotSettings2,
|
|
parametricPlot: renderParametricPlotSettings2,
|
|
regionPlot: renderRegionPlotSettings2,
|
|
contourPlot: renderContourPlotSettings2,
|
|
vectorPlot: renderVectorPlotSettings2
|
|
},
|
|
renderOptions: renderOptions(optsFields)
|
|
};
|
|
|
|
// src/modal/menus/graph/index.ts
|
|
var import_obsidian6 = require("obsidian");
|
|
var renderByDim = {
|
|
"2D": renders2D,
|
|
"3D": renders3D
|
|
};
|
|
var render = (el, modal, dim) => {
|
|
const { renderSettings: renderSettings2, renderOptions: renderOptions3 } = renderByDim[dim];
|
|
const graphs = modal.settings.graphs;
|
|
if (!graphs.length)
|
|
graphs[0] = defaultGraph("graph_0", "plot");
|
|
let count = 0;
|
|
let dropdown;
|
|
new import_obsidian6.Setting(el).setName("Graphs").addDropdown((component) => {
|
|
dropdown = component;
|
|
component.addOptions({
|
|
[graphs[0].id]: graphs[0].id,
|
|
add: "+ add"
|
|
}).onChange((value) => {
|
|
if (value === "add") {
|
|
const name = `graph_${++count}`;
|
|
graphs.push(defaultGraph(name, "plot"));
|
|
component.addOption(name, name);
|
|
component.selectEl.remove(
|
|
component.selectEl.selectedIndex
|
|
);
|
|
component.addOption("add", "+ add");
|
|
component.setValue(name);
|
|
}
|
|
renderSelectedGraphSettings();
|
|
});
|
|
}).addButton(
|
|
(component) => component.setButtonText("Delete").setWarning().onClick((e) => {
|
|
e.preventDefault();
|
|
if (dropdown.selectEl.options.length === 2)
|
|
return;
|
|
const idxToRmv = graphs.findIndex(
|
|
(graph) => graph.id === dropdown.selectEl.options[dropdown.selectEl.selectedIndex].value
|
|
);
|
|
graphs.splice(idxToRmv, 1);
|
|
dropdown.selectEl.remove(dropdown.selectEl.selectedIndex);
|
|
renderSelectedGraphSettings();
|
|
})
|
|
);
|
|
const selectedGraphEl = el.createDiv();
|
|
const renderSelectedGraphSettings = () => {
|
|
selectedGraphEl.empty();
|
|
const graph = graphs.find(
|
|
(graph2) => graph2.id === dropdown.selectEl.options[dropdown.selectEl.selectedIndex].value
|
|
);
|
|
if (!graph)
|
|
return;
|
|
new import_obsidian6.Setting(selectedGraphEl.createDiv()).setName("Type").addDropdown((component) => {
|
|
component.addOptions(graphTypesOptions);
|
|
component.setValue(graph.type);
|
|
component.onChange((value) => {
|
|
graph.type = value;
|
|
renderSelectedGraphSettings();
|
|
});
|
|
}).setDesc(graphTypeDescription[graph.type]);
|
|
renderSettings2[graph.type](selectedGraphEl, graph[graph.type]);
|
|
renderOptions3(selectedGraphEl, modal.settings, graph.options);
|
|
};
|
|
renderSelectedGraphSettings();
|
|
};
|
|
var renderGraphSettings = (el, modal) => {
|
|
el.empty();
|
|
el.createEl("h5", { text: `Plot ${modal.settings.raster.dim}` });
|
|
render(el, modal, modal.settings.raster.dim);
|
|
};
|
|
|
|
// src/modal/menus/raster.ts
|
|
var import_obsidian7 = require("obsidian");
|
|
var renderRasterSettings = (el, graphSettingsEl, modal) => {
|
|
const settings = modal.settings;
|
|
el.createEl("h5", { text: "Raster settings" });
|
|
new import_obsidian7.Setting(el).setName("Dimensions").addDropdown((component) => {
|
|
component.addOptions({
|
|
"2D": "2D",
|
|
"3D": "3D"
|
|
});
|
|
component.onChange((value) => {
|
|
settings.raster.dim = value;
|
|
renderGraphSettings(graphSettingsEl, modal);
|
|
});
|
|
component.setValue(settings.raster.dim);
|
|
});
|
|
new import_obsidian7.Setting(el.createDiv()).addText(
|
|
(text) => text.setValue(settings.raster.background).onChange((value) => settings.raster.background = value)
|
|
).setName("Background");
|
|
new import_obsidian7.Setting(el.createDiv()).addText(
|
|
(text) => text.setValue(settings.raster.size.height).onChange((value) => settings.raster.size.height = value)
|
|
).setName("Height");
|
|
new import_obsidian7.Setting(el.createDiv()).addText(
|
|
(text) => text.setValue(settings.raster.size.width).onChange((value) => settings.raster.size.width = value)
|
|
).setName("Width");
|
|
};
|
|
|
|
// src/_constants.ts
|
|
var PLUGIN = {
|
|
CODEBLOCK_NAME: "mathematica-plot"
|
|
};
|
|
|
|
// src/modal/menus/graph/submit.ts
|
|
var import_obsidian8 = require("obsidian");
|
|
var cleanSettingStructure = (settings) => {
|
|
const cleanGraphs = settings.graphs.map((graph) => ({
|
|
id: graph.id,
|
|
options: graph.options,
|
|
type: graph.type,
|
|
[graph.type]: graph[graph.type]
|
|
}));
|
|
return { ...settings, graphs: cleanGraphs };
|
|
};
|
|
var renderSubmitBtn = (el, modal) => {
|
|
new import_obsidian8.Setting(el).addButton(
|
|
(btn) => btn.setButtonText("Submit").setCta().onClick(async () => {
|
|
const line = modal.editor.getCursor().line;
|
|
if (modal.options.isEditing) {
|
|
modal.editor.replaceSelection(
|
|
(0, import_obsidian8.stringifyYaml)(cleanSettingStructure(modal.settings))
|
|
);
|
|
} else
|
|
modal.editor.setLine(
|
|
line,
|
|
`\`\`\`${PLUGIN.CODEBLOCK_NAME}
|
|
${(0, import_obsidian8.stringifyYaml)(
|
|
cleanSettingStructure(modal.settings)
|
|
)}
|
|
\`\`\``
|
|
);
|
|
modal.options.afterSubmit(el);
|
|
modal.close();
|
|
})
|
|
);
|
|
};
|
|
|
|
// src/modal/menus/settings.ts
|
|
var renderSettings = (el, modal) => {
|
|
const rasterEl = el.createDiv();
|
|
const generalEl = el.createDiv();
|
|
const menuEl = el.createDiv();
|
|
renderRasterSettings(rasterEl, menuEl, modal);
|
|
renderGeneralSettings(generalEl, modal);
|
|
renderGraphSettings(menuEl, modal);
|
|
renderSubmitBtn(el, modal);
|
|
};
|
|
|
|
// src/modal/plotModal.ts
|
|
var import_obsidian9 = require("obsidian");
|
|
var defaultSettings = {
|
|
isEditing: false,
|
|
afterSubmit: () => null,
|
|
onClose: () => null
|
|
};
|
|
var defaultPlotSettings = () => ({
|
|
raster: {
|
|
dim: "2D",
|
|
background: "None",
|
|
size: {
|
|
height: "Automatic",
|
|
width: "250"
|
|
}
|
|
},
|
|
general: {
|
|
axes: "True",
|
|
axesLabel: "{x, y}",
|
|
frame: "False",
|
|
boxed: "True"
|
|
},
|
|
graphs: []
|
|
});
|
|
var PlotModal = class extends import_obsidian9.Modal {
|
|
constructor(plugin, editor, settings, options) {
|
|
super(plugin.app);
|
|
this.settings = defaultPlotSettings();
|
|
this.plugin = plugin;
|
|
this.editor = editor;
|
|
if (settings)
|
|
this.settings = settings;
|
|
this.options = { ...defaultSettings, ...options };
|
|
}
|
|
onOpen() {
|
|
const { contentEl } = this;
|
|
this.modalEl.addClass("mathematica-plot-modal");
|
|
contentEl.createEl("h4", { text: "Plot" });
|
|
const flex = contentEl.createEl("div", {
|
|
cls: "mathematica-plot-modal-content-container"
|
|
});
|
|
const settings = flex.createDiv();
|
|
const preview = flex.createDiv();
|
|
settings.addClass("mathematica-plot-modal-settings");
|
|
preview.addClass("mathematica-plot-modal-preview");
|
|
renderSettings(settings, this);
|
|
renderGraphPreview(preview, this);
|
|
}
|
|
onClose() {
|
|
this.options.onClose();
|
|
}
|
|
};
|
|
|
|
// src/settingsTab.ts
|
|
var import_obsidian10 = require("obsidian");
|
|
var MathematicaPlotSettingsTab = class extends import_obsidian10.PluginSettingTab {
|
|
constructor(app, plugin) {
|
|
super(app, plugin);
|
|
this.plugin = plugin;
|
|
}
|
|
display() {
|
|
const { containerEl } = this;
|
|
containerEl.empty();
|
|
containerEl.createEl("h3").setText("Settings");
|
|
new import_obsidian10.Setting(containerEl).setName("Use cloud").setDesc(
|
|
"Whether to pass --cloud option. If you don't have the wolfram engine installed set it to true."
|
|
).addToggle(
|
|
(component) => component.setValue(this.plugin.settings.useCloud).onChange(async (value) => {
|
|
this.plugin.settings.useCloud = value;
|
|
await this.plugin.saveSettings();
|
|
})
|
|
);
|
|
new import_obsidian10.Setting(containerEl).setName("WolframScript path").setDesc(
|
|
"The installation path of WolframScript. If you WolframScript is globally available on your system you can leave it blank."
|
|
).addText(
|
|
(component) => component.setValue(this.plugin.settings.wolframScriptPath).onChange(async (value) => {
|
|
this.plugin.settings.wolframScriptPath = value;
|
|
await this.plugin.saveSettings();
|
|
})
|
|
);
|
|
}
|
|
};
|
|
|
|
// src/utils/editor.ts
|
|
var isReadingView = (markdownView) => markdownView.getMode() === "preview";
|
|
|
|
// src/main.ts
|
|
var import_os = require("os");
|
|
var DEFAULT_SETTINGS = {
|
|
useCloud: true,
|
|
wolframScriptPath: ""
|
|
};
|
|
var MathematicaPlot = class extends import_obsidian11.Plugin {
|
|
async onload() {
|
|
if (import_obsidian11.Platform.isMobile)
|
|
return;
|
|
await this.loadSettings();
|
|
this.addCommand({
|
|
id: "plot-graph",
|
|
name: "Plot Graph",
|
|
editorCallback: (editor) => {
|
|
new PlotModal(this, editor, null, {}).open();
|
|
}
|
|
});
|
|
this.registerMarkdownCodeBlockProcessor(
|
|
PLUGIN.CODEBLOCK_NAME,
|
|
async (source, el) => {
|
|
const plotEl = el.createDiv({ cls: "mathematica-plot" });
|
|
await renderGraph(plotEl, source, {
|
|
...this.settings
|
|
});
|
|
const view = this.app.workspace.getActiveViewOfType(import_obsidian11.MarkdownView);
|
|
if (!view || isReadingView(view))
|
|
return;
|
|
const cursorPos = view.editor.getCursor();
|
|
const button = new import_obsidian11.ExtraButtonComponent(plotEl).setIcon("settings-2").setTooltip("Edit plot settings").onClick(() => {
|
|
var _a, _b;
|
|
(_b = (_a = el.parentElement) == null ? void 0 : _a.querySelector(".edit-block-button")) == null ? void 0 : _b.click();
|
|
const settings = (0, import_obsidian11.parseYaml)(source);
|
|
settings.graphs = settings.graphs.map((graph) => ({
|
|
...defaultGraphType(),
|
|
...graph
|
|
}));
|
|
new PlotModal(this, view.editor, settings, {
|
|
isEditing: true,
|
|
onClose: () => view.editor.setCursor(cursorPos)
|
|
}).open();
|
|
});
|
|
button.extraSettingsEl.addClass("mathematica-plot-edit-btn");
|
|
}
|
|
);
|
|
this.addSettingTab(new MathematicaPlotSettingsTab(this.app, this));
|
|
}
|
|
onunload() {
|
|
}
|
|
async loadSettings() {
|
|
if ((0, import_os.platform)() === "win32")
|
|
DEFAULT_SETTINGS.wolframScriptPath = "C:\\Program Files\\Wolfram Research\\WolframScript\\wolframscript.exe";
|
|
this.settings = Object.assign(
|
|
{},
|
|
DEFAULT_SETTINGS,
|
|
await this.loadData()
|
|
);
|
|
}
|
|
async saveSettings() {
|
|
await this.saveData(this.settings);
|
|
}
|
|
};
|
|
|
|
/* nosourcemap */ |