feat: add some kirchhoffs law

This commit is contained in:
max_richter 2022-03-10 20:49:52 +01:00
parent 7427cd4657
commit 9966ab367f
33 changed files with 5 additions and 2130 deletions

3
.obsidian/app.json vendored
View File

@ -1,3 +0,0 @@
{
"legacyEditor": false
}

View File

@ -1,3 +0,0 @@
{
"baseFontSize": 16
}

View File

@ -1 +0,0 @@
[]

View File

@ -1,15 +0,0 @@
[
"file-explorer",
"global-search",
"switcher",
"graph",
"backlink",
"page-preview",
"note-composer",
"command-palette",
"editor-status",
"markdown-importer",
"word-count",
"open-with-default-app",
"file-recovery"
]

View File

@ -1 +0,0 @@
{}

View File

@ -1 +0,0 @@
/main.js linguist-generated

View File

@ -1,2 +0,0 @@
/data.json
/node_modules/

View File

@ -1,3 +0,0 @@
{
"tabWidth": 4
}

View File

@ -1,95 +0,0 @@
# Obsidian Desmos
Render [Desmos](https://www.desmos.com/calculator) graphs right inside your notes.
# Installation
## Using Git
If your vault is hosted using git then congratulations, you can use the easy method. Run
`git subtree add --prefix .obsidian/plugins/obsidian-desmos https://github.com/Nigecat/obsidian-desmos master --squash`
to add the plugin to the vault in the current working directory of your terminal.
You can then run
`git subtree pull --prefix .obsidian/plugins/obsidian-desmos https://github.com/Nigecat/obsidian-desmos master --squash`
to update the plugin to the latest version (from the same working directory).
## Using anything else
Alternatively, if you do not use git or are not comfortable using the terminal, you can manually install the plugin. Download [manifest.json](manifest.json), [versions.json](versions.json), and [main.js](main.js) and place them in `<vault>/.obsidian/plugins/obsidian-desmos` (you may have to create any missing folders).
This process must be repeated to update the application.
# Usage
The most basic usage of this plugin involves creating a codeblock with the tag `desmos-graph` and placing the equations you wish to graph in the body:
````
```desmos-graph
y=x
```
````
Equations use the [LaTeX math](https://en.wikibooks.org/wiki/LaTeX/Mathematics) format and you can graph multiple equations by placing each one on a seperate line:
````
```desmos-graph
y=\sin(x)
y=\frac{1}{x}
```
````
You can restrict the bounds of the graph and apply other settings by placing a `---` seperator before your equations. The content before it must be a set of `key=value` pairs seperated by either **newlines or semicolons** (or both):
````
```desmos-graph
boundary_left=0; boundary_right=100;
boundary_top=10; boundary_bottom=-10;
---
y=\sin(x)
```
````
You can set the dimensions of the rendered image by using the `height` and `width` fields.
#### Restrictions
Note that graph restrictions follow the same format as desmos itself (except we use a `|` to denote the beginning of the restrictions):
````
```desmos-graph
y=\sin(x)|{y > 0}
```
````
### Style
We support six different types of (case-insensitive) styles:
Line: `SOLID` `DASHED` `DOTTED`
Point: `POINT` `OPEN` `CROSS`
These are placed after the graph restrictions, following another `|`:
````
```desmos-graph
y=\sin(x)|{y > 0}|DASHED
```
````
If you do not wish to apply any restrictions, the center field can be left blank:
````
```desmos-graph
y=\sin(x)||DASHED
(1,2)||OPEN
```
````
## Important
Note that to be able to render these graphs into a PDF the following conditions must be fulfilled
1. Memory caching **must** be enabled
2. Obsidian **must** have been restarted since you initially created the graph
3. You **must** have viewed the rendered graph in the preview since the restart
After these are complete, a standard PDF export should work fine.
In the future these steps will be removed and you will be able to directly export them.

File diff suppressed because one or more lines are too long

View File

@ -1,9 +0,0 @@
{
"id": "obsidian-desmos",
"name": "Desmos",
"version": "0.0.1",
"minAppVersion": "0.9.12",
"description": "Embed Desmos graphs into your notes",
"author": "Nigecat",
"isDesktopOnly": true
}

View File

@ -1,343 +0,0 @@
{
"name": "obsidian-desmos",
"version": "0.0.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@rollup/plugin-commonjs": {
"version": "19.0.0",
"resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-19.0.0.tgz",
"integrity": "sha512-adTpD6ATGbehdaQoZQ6ipDFhdjqsTgpOAhFiPwl+dzre4pPshsecptDPyEFb61JMJ1+mGljktaC4jI8ARMSNyw==",
"dev": true,
"requires": {
"@rollup/pluginutils": "^3.1.0",
"commondir": "^1.0.1",
"estree-walker": "^2.0.1",
"glob": "^7.1.6",
"is-reference": "^1.2.1",
"magic-string": "^0.25.7",
"resolve": "^1.17.0"
}
},
"@rollup/plugin-node-resolve": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.0.0.tgz",
"integrity": "sha512-41X411HJ3oikIDivT5OKe9EZ6ud6DXudtfNrGbC4nniaxx2esiWjkLOzgnZsWq1IM8YIeL2rzRGLZLBjlhnZtQ==",
"dev": true,
"requires": {
"@rollup/pluginutils": "^3.1.0",
"@types/resolve": "1.17.1",
"builtin-modules": "^3.1.0",
"deepmerge": "^4.2.2",
"is-module": "^1.0.0",
"resolve": "^1.19.0"
}
},
"@rollup/plugin-typescript": {
"version": "8.2.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.2.1.tgz",
"integrity": "sha512-Qd2E1pleDR4bwyFxqbjt4eJf+wB0UKVMLc7/BAFDGVdAXQMCsD4DUv5/7/ww47BZCYxWtJqe1Lo0KVNswBJlRw==",
"dev": true,
"requires": {
"@rollup/pluginutils": "^3.1.0",
"resolve": "^1.17.0"
}
},
"@rollup/pluginutils": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
"integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
"dev": true,
"requires": {
"@types/estree": "0.0.39",
"estree-walker": "^1.0.1",
"picomatch": "^2.2.2"
},
"dependencies": {
"estree-walker": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
"integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
"dev": true
}
}
},
"@types/codemirror": {
"version": "0.0.108",
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.108.tgz",
"integrity": "sha512-3FGFcus0P7C2UOGCNUVENqObEb4SFk+S8Dnxq7K6aIsLVs/vDtlangl3PEO0ykaKXyK56swVF6Nho7VsA44uhw==",
"dev": true,
"requires": {
"@types/tern": "*"
}
},
"@types/debounce": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@types/debounce/-/debounce-1.2.0.tgz",
"integrity": "sha512-bWG5wapaWgbss9E238T0R6bfo5Fh3OkeoSt245CM7JJwVwpw6MEBCbIxLq5z8KzsE3uJhzcIuQkyiZmzV3M/Dw==",
"dev": true
},
"@types/estree": {
"version": "0.0.39",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
"dev": true
},
"@types/node": {
"version": "15.12.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz",
"integrity": "sha512-zjQ69G564OCIWIOHSXyQEEDpdpGl+G348RAKY0XXy9Z5kU9Vzv1GMNnkar/ZJ8dzXB3COzD9Mo9NtRZ4xfgUww==",
"dev": true
},
"@types/resolve": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
"integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/tern": {
"version": "0.23.3",
"resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.3.tgz",
"integrity": "sha512-imDtS4TAoTcXk0g7u4kkWqedB3E4qpjXzCpD2LU5M5NAXHzCDsypyvXSaG7mM8DKYkCRa7tFp4tS/lp/Wo7Q3w==",
"dev": true,
"requires": {
"@types/estree": "*"
}
},
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"builtin-modules": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz",
"integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==",
"dev": true
},
"commondir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
"dev": true
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"deepmerge": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
"dev": true
},
"estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"optional": true
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
"glob": {
"version": "7.1.7",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
"integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
"requires": {
"function-bind": "^1.1.1"
}
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"is-core-module": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz",
"integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==",
"dev": true,
"requires": {
"has": "^1.0.3"
}
},
"is-module": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
"integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=",
"dev": true
},
"is-reference": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
"integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==",
"dev": true,
"requires": {
"@types/estree": "*"
}
},
"magic-string": {
"version": "0.25.7",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
"integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==",
"dev": true,
"requires": {
"sourcemap-codec": "^1.4.4"
}
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==",
"dev": true
},
"obsidian": {
"version": "0.12.5",
"resolved": "https://registry.npmjs.org/obsidian/-/obsidian-0.12.5.tgz",
"integrity": "sha512-dQkcHWVgPzVlCxvkeu02Co8P1t4Ii95dC2NsFJV5bKK04J4//YxEdTTI/TFKr77CtYcH78LlUmOFeY5rHwyU/Q==",
"dev": true,
"requires": {
"@types/codemirror": "0.0.108",
"moment": "2.29.1"
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": {
"wrappy": "1"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true
},
"path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true
},
"picomatch": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
"integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
"dev": true
},
"resolve": {
"version": "1.20.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
"integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
"dev": true,
"requires": {
"is-core-module": "^2.2.0",
"path-parse": "^1.0.6"
}
},
"rollup": {
"version": "2.51.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.51.2.tgz",
"integrity": "sha512-ReV2eGEadA7hmXSzjxdDKs10neqH2QURf2RxJ6ayAlq93ugy6qIvXMmbc5cWMGCDh1h5T4thuWO1e2VNbMq8FA==",
"dev": true,
"requires": {
"fsevents": "~2.3.1"
}
},
"sourcemap-codec": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
"dev": true
},
"tslib": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
"dev": true
},
"typescript": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz",
"integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==",
"dev": true
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
}
}
}

View File

@ -1,22 +0,0 @@
{
"name": "obsidian-desmos",
"version": "0.0.1",
"description": "Embed Desmos graphs into your notes",
"main": "main.js",
"author": "Nigecat",
"scripts": {
"build": "rollup --config rollup.config.js --environment BUILD:production",
"build:dev": "rollup --config rollup.config.js -w"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^19.0.0",
"@rollup/plugin-node-resolve": "^13.0.0",
"@rollup/plugin-typescript": "^8.2.1",
"@types/debounce": "^1.2.0",
"@types/node": "^15.12.2",
"obsidian": "^0.12.5",
"rollup": "^2.51.2",
"tslib": "^2.3.0",
"typescript": "^4.3.2"
}
}

View File

@ -1,18 +0,0 @@
import typescript from "@rollup/plugin-typescript";
import { nodeResolve } from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
const isProd = process.env.BUILD === "production";
export default {
input: "src/main.ts",
output: {
dir: ".",
sourcemap: "inline",
sourcemapExcludeSources: isProd,
format: "cjs",
exports: "default",
},
external: ["obsidian"],
plugins: [typescript(), nodeResolve({ browser: true }), commonjs()],
};

View File

@ -1,141 +0,0 @@
import { createHash } from "crypto";
export interface Fields {
width: number;
height: number;
boundary_left: number;
boundary_right: number;
boundary_bottom: number;
boundary_top: number;
}
const FIELD_DEFAULTS: Fields = {
width: 600,
height: 400,
boundary_left: -10,
boundary_right: 10,
boundary_bottom: -7,
boundary_top: 7,
};
export class Dsl {
/** A (hex) SHA-256 hash of the fields of this object */
public readonly hash: string;
public readonly equations: string[];
public readonly fields: Fields;
private constructor(equations: string[], fields: Partial<Fields>) {
this.equations = equations;
this.fields = { ...FIELD_DEFAULTS, ...fields };
Dsl.assert_sanity(this.fields);
this.hash = createHash("sha256")
.update(JSON.stringify(this))
.digest("hex");
}
/** Check if the fields are sane, throws a `SyntaxError` if they aren't */
private static assert_sanity(fields: Fields) {
// Ensure boundaries are complete and in order
if (fields.boundary_left >= fields.boundary_right) {
throw new SyntaxError(
`Right boundary (${fields.boundary_right}) must be greater than left boundary (${fields.boundary_left})`
);
}
if (fields.boundary_bottom >= fields.boundary_top) {
throw new SyntaxError(`
Top boundary (${fields.boundary_top}) must be greater than bottom boundary (${fields.boundary_bottom})
`);
}
}
public static parse(source: string): Dsl {
const split = source.split("---");
let equations: string[];
let fields: Partial<Fields>;
switch (split.length) {
case 0: {
equations = [];
break;
}
case 1: {
equations = split[0].split("\n").filter(Boolean);
break;
}
case 2: {
// If there are two segments then we know the first one must contain the settings
fields = split[0]
// Allow either a newline or semicolon as a delimiter
.split(/[;\n]+/)
.map((setting) => setting.trim())
// Remove any empty elements
.filter(Boolean)
// Split each field on the first equals sign to create the key=value pair
.map((setting) => {
const [key, ...value] = setting.split("=");
return [key, value.join("=")];
})
.reduce((settings, [key, value]) => {
if (FIELD_DEFAULTS.hasOwnProperty(key)) {
if (!value) {
throw new SyntaxError(
`Field '${key}' must have a value`
);
}
// We can use the defaults to determine the type of each field
const field_v = (FIELD_DEFAULTS as any)[key];
const field_t = typeof field_v;
switch (field_t) {
case "number": {
const s = parseInt(value);
if (Number.isNaN(s)) {
throw new SyntaxError(
`Field '${key}' must have an integer value`
);
}
(settings as any)[key] = s;
break;
}
case "string": {
(settings as any)[key] = value;
break;
}
case "object": {
const val = JSON.parse(value);
if (
val.constructor === field_v.constructor
) {
(settings as any)[key] = val;
}
break;
}
}
} else {
throw new SyntaxError(`Unrecognised field: ${key}`);
}
return settings;
}, {} as Partial<Fields>);
equations = split[1].split("\n").filter(Boolean);
break;
}
default: {
fields = {};
}
}
if (!equations) {
throw new SyntaxError("Too many segments");
}
return new Dsl(equations, fields);
}
}

View File

@ -1,6 +0,0 @@
export function renderError(err: string, el: HTMLElement) {
el.innerHTML = `
<div style="padding: 20px; background-color: #f44336; color: white;">
<strong>Desmos Graph Error:</strong> ${err}
</div>`;
}

View File

@ -1,64 +0,0 @@
import { Dsl } from "./dsl";
import { Renderer } from "./renderer";
import { renderError } from "./error";
import { debounce, Plugin } from "obsidian";
import { Settings, SettingsTab, DEFAULT_SETTINGS } from "./settings";
export default class Desmos extends Plugin {
settings: Settings;
/** Helper for in-memory graph caching */
graph_cache: Record<string, string>;
async onload() {
this.graph_cache = {};
await this.loadSettings();
this.addSettingTab(new SettingsTab(this.app, this));
// Keep track of the total number of graphs in each file
// This allows us to skip the debounce on recently opened files to make it feel snappier to use
let total = 0;
this.app.workspace.on("file-open", async (file) => {
const contents = await this.app.vault.cachedRead(file);
// Attempt to figure out the number of graphs there are in this file
// In this case it is fine if we overestimate because we only need a general idea since this just makes it skip the debounce
total = (contents.match(/```desmos-graph/g) || []).length;
});
const render = (source: string, el: HTMLElement) => {
try {
Renderer.render(Dsl.parse(source), this.settings, el, this);
} catch (err) {
renderError(err.message, el);
}
};
const debounce_render = debounce(
(source: string, el: HTMLElement) => render(source, el),
this.settings.debounce
);
this.registerMarkdownCodeBlockProcessor(
"desmos-graph",
(source, el) => {
if (total > 0) {
total--;
// Skip the debounce on initial render
render(source, el);
} else {
debounce_render(source, el);
}
}
);
}
async loadSettings() {
this.settings = Object.assign(
{},
DEFAULT_SETTINGS,
await this.loadData()
);
}
async saveSettings() {
await this.saveData(this.settings);
}
}

View File

@ -1,205 +0,0 @@
import path from "path";
import Desmos from "./main";
import { Dsl } from "./dsl";
import { tmpdir } from "os";
import { Notice } from "obsidian";
import { Settings } from "./settings";
import { renderError } from "./error";
import { existsSync, promises as fs } from "fs";
export class Renderer {
static render(
args: Dsl,
settings: Settings,
el: HTMLElement,
plugin: Desmos
) {
const { fields, equations, hash } = args;
// Calculate cache info for filesystem caching
const vault_root = (plugin.app.vault.adapter as any).basePath;
const cache_dir = settings.cache_directory
? path.isAbsolute(settings.cache_directory)
? settings.cache_directory
: path.join(vault_root, settings.cache_directory)
: tmpdir();
const cache_target = path.join(cache_dir, `desmos-graph-${hash}.png`);
// If this graph is in the cache then fetch it
if (settings.cache) {
if (
settings.cache_location == "memory" &&
hash in plugin.graph_cache
) {
const data = plugin.graph_cache[hash];
const img = document.createElement("img");
img.src = data;
el.appendChild(img);
return;
} else if (
settings.cache_location == "filesystem" &&
existsSync(cache_target)
) {
fs.readFile(cache_target).then((data) => {
const b64 =
"data:image/png;base64," +
Buffer.from(data).toString("base64");
const img = document.createElement("img");
img.src = b64;
el.appendChild(img);
});
return;
}
}
const expressions = equations.map(
(equation) =>
`calculator.setExpression({
latex: "${equation.split("|")[0].replace("\\", "\\\\")}${(
equation.split("|")[1] ?? ""
)
.replace("{", "\\\\{")
.replace("}", "\\\\}")
.replace("<=", "\\\\leq ")
.replace(">=", "\\\\geq ")
.replace("<", "\\\\le ")
.replace(">", "\\\\ge ")}",
${(() => {
const mode = equation.split("|")[2];
if (mode) {
if (
["solid", "dashed", "dotted"].contains(
mode.toLowerCase()
)
) {
return `lineStyle: Desmos.Styles.${mode.toUpperCase()}`;
} else if (
["point", "open", "cross"].contains(
mode.toLowerCase()
)
) {
return `pointStyle: Desmos.Styles.${mode.toUpperCase()}`;
}
}
return "";
})()}
});`
);
// Because of the electron sandboxing we have to do this inside an iframe,
// otherwise we can't include the desmos API (although it would be nice if they had a REST API of some sort)
const html_src_head = `<script src="https://www.desmos.com/api/v1.6/calculator.js?apiKey=dcb31709b452b1cf9dc26972add0fda6"></script>`;
const html_src_body = `
<div id="calculator" style="width: ${fields.width}px; height: ${
fields.height
}px;"></div>
<script>
const options = {
settingsMenu: false,
expressions: false,
lockViewPort: true,
zoomButtons: false,
trace: false,
};
const calculator = Desmos.GraphingCalculator(document.getElementById("calculator"), options);
calculator.setMathBounds({
left: ${fields.boundary_left},
right: ${fields.boundary_right},
top: ${fields.boundary_top},
bottom: ${fields.boundary_bottom},
});
${expressions.join("")}
calculator.observe("expressionAnalysis", () => {
for (const id in calculator.expressionAnalysis) {
const analysis = calculator.expressionAnalysis[id];
if (analysis.isError) {
parent.postMessage({ t: "desmos-graph", d: "error", data: analysis.errorMessage, hash: "${hash}" });
}
}
});
calculator.asyncScreenshot({ showLabels: true, format: "png" }, (data) => {
document.body.innerHTML = "";
parent.postMessage({ t: "desmos-graph", d: "render", data, hash: "${hash}" }, "app://obsidian.md");
});
</script>
`;
const html_src = `<html><head>${html_src_head}</head><body>${html_src_body}</body>`;
const iframe = document.createElement("iframe");
iframe.width = fields.width.toString();
iframe.height = fields.height.toString();
iframe.style.border = "none";
iframe.scrolling = "no"; // fixme use a non-depreciated function
iframe.srcdoc = html_src;
// iframe.style.display = "none"; //fixme hiding the iframe breaks the positioning
el.appendChild(iframe);
const handler = (
message: MessageEvent<{
t: string;
d: string;
data: string;
hash: string;
}>
) => {
if (
message.origin === "app://obsidian.md" &&
message.data.t === "desmos-graph" &&
message.data.hash === hash
) {
el.empty();
if (message.data.d === "error") {
renderError(message.data.data, el);
}
if (message.data.d === "render") {
const { data } = message.data;
window.removeEventListener("message", handler);
const img = document.createElement("img");
img.src = data;
el.appendChild(img);
if (settings.cache) {
if (settings.cache_location == "memory") {
plugin.graph_cache[hash] = data;
} else if (settings.cache_location == "filesystem") {
if (existsSync(cache_dir)) {
fs.writeFile(
cache_target,
data.replace(
/^data:image\/png;base64,/,
""
),
"base64"
).catch(
(err) =>
new Notice(
`desmos-graph: unexpected error when trying to cache graph: ${err}`,
10000
)
);
} else {
new Notice(
`desmos-graph: cache directory not found: '${cache_dir}'`,
10000
);
}
}
}
}
}
};
window.addEventListener("message", handler);
}
}

View File

@ -1,105 +0,0 @@
import { tmpdir } from "os";
import Desmos from "./main";
import { PluginSettingTab, App, Setting } from "obsidian";
export interface Settings {
debounce: number;
cache: boolean;
cache_location: "memory" | "filesystem";
cache_directory: string | null;
}
export const DEFAULT_SETTINGS: Settings = {
debounce: 500,
cache: true,
cache_location: "memory",
cache_directory: null,
};
export class SettingsTab extends PluginSettingTab {
plugin: Desmos;
constructor(app: App, plugin: Desmos) {
super(app, plugin);
this.plugin = plugin;
}
display() {
let { containerEl } = this;
containerEl.empty();
new Setting(containerEl)
.setName("Debounce Time (ms)")
.setDesc(
"How long to wait after a keypress to render the graph (requires restart to take effect)"
)
.addText((text) =>
text
.setValue(this.plugin.settings.debounce.toString())
.onChange(async (value) => {
const val = parseInt(value);
this.plugin.settings.debounce =
val === NaN ? DEFAULT_SETTINGS.debounce : val;
await this.plugin.saveSettings();
})
);
new Setting(containerEl)
.setName("Cache")
.setDesc("Whether to cache the rendered graphs")
.addToggle((toggle) =>
toggle
.setValue(this.plugin.settings.cache)
.onChange(async (value) => {
this.plugin.settings.cache = value;
await this.plugin.saveSettings();
// Reset the display so the new state can render
this.display();
})
);
if (this.plugin.settings.cache) {
new Setting(containerEl)
.setName("Cache in memory (alternate: filesystem)")
.setDesc(
"Cache rendered graphs in memory or on the filesystem (note that memory caching is not persistent)."
)
.addToggle((toggle) =>
toggle
.setValue(
this.plugin.settings.cache_location === "memory"
? true
: false
)
.onChange(async (value) => {
this.plugin.settings.cache_location = value
? "memory"
: "filesystem";
await this.plugin.saveSettings();
// Reset the display so the new state can render
this.display();
})
);
if (this.plugin.settings.cache_location == "filesystem") {
new Setting(containerEl)
.setName("Cache Directory")
.setDesc(
"The directory to save cached graphs in (technical note: the graphs will be saved as `desmos-graph-<hash>.png` where the name is a SHA-256 hash of the graph source). The default directory is the system tempdir for your current operating system, and this value may be either a path relative to the root of your vault or an absolute path. Also note that a lot of junk will be saved to this folder, you have been warned."
)
.addText((text) =>
text
.setPlaceholder(tmpdir())
.setValue(this.plugin.settings.cache_directory)
.onChange(async (value) => {
this.plugin.settings.cache_directory = value;
await this.plugin.saveSettings();
})
);
}
}
}
}

View File

@ -1,3 +0,0 @@
*
!.gitignore
!/plugins/**/*

View File

@ -1 +0,0 @@
../../../../main.js

View File

@ -1 +0,0 @@
../../../../manifest.json

View File

@ -1 +0,0 @@
../../../../versions.json

View File

@ -1,9 +0,0 @@
```desmos-graph
boundary_left=-2; boundary_right=2;
boundary_bottom=-1; boundary_top=3;
---
y=x^2|{x<0}|DASHED
y=x||DOTTED
(1,2)||OPEN
(-1,2)||CROSS
```

View File

@ -1,16 +0,0 @@
{
"compilerOptions": {
"baseUrl": ".",
"inlineSourceMap": true,
"inlineSources": true,
"module": "ESNext",
"target": "es6",
"allowJs": true,
"noImplicitAny": true,
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"importHelpers": true,
"lib": ["dom", "es5", "scripthost", "es2015"]
},
"include": ["**/*.ts"]
}

View File

@ -1,3 +0,0 @@
{
"0.0.1": "0.9.12"
}

View File

@ -1,525 +0,0 @@
/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
var __export = (target, all) => {
__markAsModule(target);
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __reExport = (target, module2, desc) => {
if (module2 && typeof module2 === "object" || typeof module2 === "function") {
for (let key of __getOwnPropNames(module2))
if (!__hasOwnProp.call(target, key) && key !== "default")
__defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
}
return target;
};
var __toModule = (module2) => {
return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
};
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/main.ts
__export(exports, {
default: () => LatexEnvironments
});
var import_obsidian3 = __toModule(require("obsidian"));
// src/settings.ts
var LatexEnvironmentsSettings = class {
constructor() {
this.defaultEnvironment = "multline";
this.customEnvironments = [];
}
};
function ensureSettings(loaded) {
var _a, _b;
const settings = new LatexEnvironmentsSettings();
settings.defaultEnvironment = (_a = loaded.defaultEnvironment) != null ? _a : settings.defaultEnvironment;
settings.customEnvironments = (_b = loaded.customEnvironments) != null ? _b : settings.customEnvironments;
return settings;
}
// src/search.ts
var SearchCursor = class {
constructor(text, regex, _originalCaret) {
this.text = text;
this._originalCaret = _originalCaret;
if (regex instanceof RegExp) {
this.regex = regex;
} else {
this.regex = new RegExp(regex);
}
this.reset();
}
reset() {
this._from = this._originalCaret;
this._to = this._originalCaret;
this._caret = this._originalCaret;
}
findNext() {
const text = this.text.slice(this._caret);
const match = text.match(this.regex);
if ((match == null ? void 0 : match.index) == null) {
return void 0;
}
this._from = this._caret + match.index;
this._to = this._caret + match.index + match[0].length;
this._caret = this._to;
return match;
}
findPrevious() {
const reverseRegex = new RegExp(`(?<full>${this.regex.source})(?!.*[\\r\\n]*.*\\k<full>)`, this.regex.flags);
const text = this.text.slice(0, this._caret);
const lastMatch = text.match(reverseRegex);
if ((lastMatch == null ? void 0 : lastMatch.index) == null || (lastMatch == null ? void 0 : lastMatch.groups) == null) {
return void 0;
}
this._from = lastMatch.index;
this._to = lastMatch.index + lastMatch.groups.full.length;
this._caret = this._from;
return lastMatch;
}
to() {
return this._to;
}
from() {
return this._from;
}
};
// src/mathblock.ts
var MathBlock = class {
constructor(text, cursor) {
this.text = text;
const searchCursor = new SearchCursor(text, "\\$\\$", cursor);
this.startPosition = searchCursor.findPrevious() != null ? searchCursor.to() : 0;
searchCursor.reset();
this.endPosition = searchCursor.findNext() != null ? searchCursor.from() : text.length;
}
getEnclosingEnvironment(cursor) {
const beginEnds = new BeginEnds(this.text, this.startPosition, this.endPosition);
const environments = Array.from(beginEnds);
if (beginEnds.isOpen) {
throw new Error("unclosed environments in block");
}
const start = environments.filter((env) => env.type === "begin" && env.from < cursor).pop();
if (start === void 0) {
return void 0;
}
const after = environments.filter((env) => env.from > start.to);
let open = 1;
let end;
for (const env of after) {
if (env.type === "begin") {
open++;
} else {
open--;
if (open === 0) {
end = env;
break;
}
}
}
if (end === void 0) {
throw new Error("current environment is never closed");
}
if (end.to < cursor) {
return void 0;
}
return {
name: start.name,
begin: start,
end,
contents: this.text.slice(start.to, end.from)
};
}
static isMathMode(_cursor, _editor) {
return true;
}
};
var BeginEnds = class {
constructor(text, start, end) {
this.text = text;
this.start = start;
this.end = end;
this.openEnvs = [];
this.search = this.getEnvCursor(this.start);
}
reset() {
this.search = this.getEnvCursor(this.start);
}
getEnvCursor(start) {
return new SearchCursor(this.text, /\\(?<beginEnd>begin|end){\s*(?<name>[^}]+)\s*}/m, start);
}
get isOpen() {
return this.openEnvs.length > 0;
}
[Symbol.iterator]() {
this.reset();
return this;
}
next() {
const match = this.search.findNext();
const to = this.search.to();
if ((match == null ? void 0 : match.groups) == null || to > this.end) {
return { done: true, value: null };
}
switch (match.groups.beginEnd) {
case "begin": {
const current = {
name: match.groups.name,
type: "begin",
from: this.search.from(),
to: this.search.to()
};
this.openEnvs.push(current);
return {
done: false,
value: current
};
}
case "end": {
const current = this.openEnvs.pop();
if (current === void 0) {
throw new Error("closing environment which was never opened");
}
if (current.name !== match.groups.name) {
throw new Error("environment not closed properly");
}
return {
done: false,
value: {
name: match.groups.name,
type: "end",
from: this.search.from(),
to: this.search.to()
}
};
}
}
throw new Error(`regex returned unexpected result ${match[1]}`);
}
};
// src/envmodal.ts
var import_obsidian = __toModule(require("obsidian"));
// src/environmentNames.ts
var DISPLAY_EQUATIONS = [
"equation",
"equation*",
"gather",
"gather*",
"multline",
"multline*",
"split",
"align",
"align*",
"flalign",
"flalign*",
"alignat",
"alignat*"
];
var MATRICES = [
"matrix",
"pmatrix",
"bmatrix",
"Bmatrix",
"vmatrix",
"Vmatrix",
"smallmatrix"
];
var SUB_ENVIRONMENTS = ["multlined", "gathered", "aligned", "cases"];
var DEFAULT_ENVIRONMENTS = [
...DISPLAY_EQUATIONS,
...MATRICES,
...SUB_ENVIRONMENTS
];
// src/envmodal.ts
var EnvModal = class extends import_obsidian.FuzzySuggestModal {
constructor(app, settings, name, callback) {
super(app);
this.settings = settings;
this.name = name;
this.callback = callback;
this.matched = false;
this.setInstructions([
{ command: "\u2191\u2193", purpose: "to navigate" },
{ command: "\u21B5", purpose: "to select" },
{ command: "esc", purpose: "to dismiss" }
]);
this.setPlaceholder("environment name");
}
getItems() {
return Array.from(new Set([this.settings.defaultEnvironment].concat(this.settings.customEnvironments, DEFAULT_ENVIRONMENTS)));
}
getItemText(item) {
this.matched = true;
return item;
}
onNoSuggestion() {
this.matched = false;
}
onChooseItem(item, _evt) {
if (this.matched) {
this.callback(item);
} else {
this.callback(this.inputEl.value);
}
}
static callback(app, settings, defaultName, call) {
new EnvModal(app, settings, defaultName, call).open();
}
};
// src/latexEnvironmentsSettingsTab.ts
var import_obsidian2 = __toModule(require("obsidian"));
var LatexEnvironmentsSettingTab = class extends import_obsidian2.PluginSettingTab {
constructor(app, plugin) {
super(app, plugin);
this.plugin = plugin;
}
display() {
const { containerEl } = this;
containerEl.empty();
containerEl.createEl("h2", { text: "Settings for latex environments" });
new import_obsidian2.Setting(containerEl).setName("Default environment").setDesc("The default environment to insert").addText((text) => text.setPlaceholder("environment").setValue(this.plugin.settings.defaultEnvironment).onChange((value) => __async(this, null, function* () {
this.plugin.settings.defaultEnvironment = value;
yield this.plugin.saveData(this.plugin.settings);
})));
new import_obsidian2.Setting(containerEl).setName("Extra environments").setDesc("Environment names to be suggested for completion (one per line)").addTextArea((area) => {
area.setValue(this.plugin.settings.customEnvironments.join("\n")).onChange((value) => __async(this, null, function* () {
this.plugin.settings.customEnvironments = value.split("\n").map((x) => x.trim()).filter((x) => x.length > 0);
yield this.plugin.saveData(this.plugin.settings);
}));
});
}
};
// src/actions/action.ts
var Action = class {
constructor(doc) {
this.doc = doc;
}
suggestName() {
return void 0;
}
get needsName() {
return true;
}
};
// src/environment.ts
function newEnvironment(name, cursor, contents = "") {
const pad = getPad(contents);
return {
replaceSelection: `\\begin{${name}}${pad}${contents}${pad}\\end{${name}}`,
selection: {
from: {
ch: 0,
line: cursor.line + 1
}
}
};
}
function unwrapEnvironment(environment, doc) {
return {
changes: [
{
text: trim(environment.contents),
from: doc.offsetToPos(environment.begin.from),
to: doc.offsetToPos(environment.end.to)
}
],
selection: { from: doc.getCursor() }
};
}
function changeEnvironment(environment, doc, name) {
const change = {
text: `\\begin{${name}}${environment.contents}\\end{${name}}`,
from: doc.offsetToPos(environment.begin.from),
to: doc.offsetToPos(environment.end.to)
};
return {
changes: [change],
selection: { from: doc.getCursor() }
};
}
function getPad(text) {
if (text.length > 0 && text.match(/^[ \t]*$/) != null) {
return "";
}
return "\n";
}
function trim(text) {
if (text.length === 0)
return text;
const start = text.startsWith("\n") ? 1 : 0;
const end = text.endsWith("\n") ? text.length - 1 : text.length;
return text.slice(start, end);
}
// src/actions/wrapAction.ts
var WrapAction = class extends Action {
constructor(doc, addWhitespace = true) {
super(doc);
this.addWhitespace = addWhitespace;
}
prepare() {
return this;
}
transaction(envName) {
return newEnvironment(envName, this.doc.getCursor(), this.doc.getSelection());
}
};
// src/actions/insertAction.ts
var InsertAction = class extends Action {
prepare() {
if (this.doc.somethingSelected()) {
return new WrapAction(this.doc).prepare();
}
return this;
}
transaction(envName) {
return newEnvironment(envName, this.doc.getCursor());
}
};
// src/actions/changeAction.ts
var ChangeAction = class extends Action {
suggestName() {
return this.name;
}
prepare() {
const cursor = this.doc.posToOffset(this.doc.getCursor());
const block = new MathBlock(this.doc.getValue(), cursor);
this.current = block.getEnclosingEnvironment(cursor);
if (this.current === void 0) {
return new WrapAction(this.doc, block.startPosition === block.endPosition);
}
this.name = this.current.name;
return this;
}
transaction(envName) {
if (this.current !== void 0) {
return changeEnvironment(this.current, this.doc, envName);
}
return {};
}
};
// src/actions/deleteAction.ts
var DeleteAction = class extends Action {
get needsName() {
return false;
}
prepare() {
const cursor = this.doc.getCursor();
const block = new MathBlock(this.doc.getValue(), this.doc.posToOffset(cursor));
this.current = block.getEnclosingEnvironment(this.doc.posToOffset(cursor));
return this;
}
transaction(_envName) {
if (this.current !== void 0) {
return unwrapEnvironment(this.current, this.doc);
}
return {};
}
};
// src/main.ts
var LatexEnvironments = class extends import_obsidian3.Plugin {
constructor() {
super(...arguments);
this.settings = new LatexEnvironmentsSettings();
}
onload() {
return __async(this, null, function* () {
const settings = yield this.loadData();
if (settings !== null) {
this.settings = ensureSettings(settings);
}
this.addCommand({
id: "insert-latex-env",
name: "Insert LaTeX environment",
checkCallback: this.mathModeCallback(InsertAction)
});
this.addCommand({
id: "change-latex-env",
name: "Change LaTeX environment",
checkCallback: this.mathModeCallback(ChangeAction)
});
this.addCommand({
id: "delete-latex-env",
name: "Delete LaTeX environment",
checkCallback: this.mathModeCallback(DeleteAction)
});
this.addSettingTab(new LatexEnvironmentsSettingTab(this.app, this));
});
}
mathModeCallback(ActionType) {
return (checking) => {
const leaf = this.app.workspace.activeLeaf;
if (leaf.view instanceof import_obsidian3.MarkdownView) {
const editor = leaf.view.editor;
const cursor = editor.posToOffset(editor.getCursor());
if (!MathBlock.isMathMode(cursor, editor)) {
return false;
}
if (!checking) {
try {
const action = new ActionType(editor.getDoc()).prepare();
this.withPromptName(editor, action);
} catch (e) {
new import_obsidian3.Notice(e.message);
}
}
return true;
}
return false;
};
}
withPromptName(editor, action) {
const call = (envName) => {
editor.transaction(action.transaction(envName));
editor.focus();
};
if (action.needsName) {
const suggested = action.suggestName();
EnvModal.callback(this.app, this.settings, suggested !== void 0 ? suggested : this.settings.defaultEnvironment, call);
} else {
call("*");
}
}
};

View File

@ -1,10 +0,0 @@
{
"id": "obsidian-latex-environments",
"name": "Latex Environments",
"version": "0.3.0",
"description": "Allows to quickly insert and change latex environments within math environments.",
"author": "Zach Raines",
"authorUrl": "https://github.com/raineszm/obsidian-latex-environments",
"minAppVersion": "0.11.11",
"isDesktopOnly": false
}

View File

@ -1 +0,0 @@
Not Found

112
.obsidian/workspace vendored
View File

@ -1,112 +0,0 @@
{
"main": {
"id": "b5edcffa82772ae7",
"type": "split",
"children": [
{
"id": "bc097db78015bcba",
"type": "leaf",
"state": {
"type": "markdown",
"state": {
"file": "Areas/electricity/led.md.md",
"mode": "source",
"source": false
}
}
},
{
"id": "cabeee83977cea84",
"type": "leaf",
"state": {
"type": "markdown",
"state": {
"file": "Areas/electricity/led.md.md",
"mode": "preview",
"source": false
}
}
}
],
"direction": "vertical"
},
"left": {
"id": "960bd0ae12708602",
"type": "split",
"children": [
{
"id": "240323277b6ea277",
"type": "tabs",
"children": [
{
"id": "018891641805eabd",
"type": "leaf",
"state": {
"type": "file-explorer",
"state": {}
}
},
{
"id": "180e37f00da590d0",
"type": "leaf",
"state": {
"type": "search",
"state": {
"query": "",
"matchingCase": false,
"explainSearch": false,
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical"
}
}
}
]
}
],
"direction": "horizontal",
"width": 300
},
"right": {
"id": "c57c7700d46038dd",
"type": "split",
"children": [
{
"id": "aa758b15486a27c3",
"type": "tabs",
"children": [
{
"id": "a47b8cf2ccebc103",
"type": "leaf",
"state": {
"type": "backlink",
"state": {
"file": "Areas/electricity/led.md.md",
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical",
"showSearch": false,
"searchQuery": "",
"backlinkCollapsed": false,
"unlinkedCollapsed": true
}
}
}
]
}
],
"direction": "horizontal",
"width": 300,
"collapsed": true
},
"active": "bc097db78015bcba",
"lastOpenFiles": [
"Areas/electricity/led.md.md",
"Areas/electricity/glossary.md",
"Untitled 1.md",
"Areas/electricity/basics.md",
"Areas/electricity/voltage-dividers.md",
"Areas/electricity/index.md",
"Areas/electricity/voltage-divider.svg"
]
}

0
.trash/assets/ki.md Normal file
View File

View File

@ -1,3 +1,3 @@
# Image of a telephone: # Image of a telephone:
![](/api/content/TestArea/test.jpg) ![Image of a telephone](test.jpg)

View File

@ -3,11 +3,11 @@ private: true
--- ---
# JimFX's Personal Wiki # JimFX's Personal Wiki
[Ressources](Ressources) [Ressources](Ressources/index.md)
[Archive](Archive) [Archive](Archive/index.md)
[Projects](Projects) [Projects](Projects/index.md)
[Areas](Areas) [Areas](Areas/index.md)