mirror of
https://github.com/youfoundjk/TeXcore.git
synced 2026-07-22 07:33:31 +00:00
Fixed pdf export
This commit is contained in:
parent
47b7ad4639
commit
e8e9b3e93e
18 changed files with 793 additions and 580 deletions
|
|
@ -3,9 +3,10 @@ import process from "process";
|
|||
import builtins from "builtin-modules";
|
||||
import fs from "fs";
|
||||
import inlineWorkerPlugin from "esbuild-plugin-inline-worker";
|
||||
import esbuildSvelte from "esbuild-svelte";
|
||||
|
||||
const banner =
|
||||
`/*
|
||||
`/*
|
||||
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||||
if you want to view the source, please visit the github repository of this plugin
|
||||
*/
|
||||
|
|
@ -19,7 +20,7 @@ const context = await esbuild.context({
|
|||
},
|
||||
entryPoints: ["src/main.ts"],
|
||||
bundle: true,
|
||||
plugins: [inlineWorkerPlugin()],
|
||||
plugins: [inlineWorkerPlugin(), esbuildSvelte({ compilerOptions: { css: "injected" } })],
|
||||
external: [
|
||||
"obsidian",
|
||||
"electron",
|
||||
|
|
@ -41,7 +42,7 @@ const context = await esbuild.context({
|
|||
minify: prod,
|
||||
sourcemap: prod ? false : "inline",
|
||||
treeShaking: true,
|
||||
outfile: "../plugin-full-calendar/obsidian-dev-vault/.obsidian/plugins/Latex-like-equations/main.js",
|
||||
outfile: "../plugin-full-calendar/obsidian-dev-vault/.obsidian/plugins/Latex-like-equations/main.js", // Ensure this path is correct for your setup
|
||||
});
|
||||
|
||||
if (prod) {
|
||||
|
|
@ -51,4 +52,4 @@ if (prod) {
|
|||
await context.watch();
|
||||
}
|
||||
|
||||
fs.copyFileSync("styles/main.css", "../plugin-full-calendar/obsidian-dev-vault/.obsidian/plugins/Latex-like-equations/styles.css");
|
||||
fs.copyFileSync("src/styles/main.css", "../plugin-full-calendar/obsidian-dev-vault/.obsidian/plugins/Latex-like-equations/styles.css");
|
||||
458
package-lock.json
generated
458
package-lock.json
generated
|
|
@ -11,6 +11,7 @@
|
|||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@lezer/common": "^1.0.3",
|
||||
"@lucide/svelte": "^0.562.0",
|
||||
"esbuild": "^0.25.12",
|
||||
"esbuild-plugin-inline-worker": "^0.1.1",
|
||||
"flatqueue": "^2.0.3",
|
||||
|
|
@ -24,9 +25,11 @@
|
|||
"@typescript-eslint/parser": "5.29.0",
|
||||
"builtin-modules": "3.3.0",
|
||||
"deepmerge": "^4.3.1",
|
||||
"esbuild-svelte": "^0.9.4",
|
||||
"obsidian": "latest",
|
||||
"p-limit": "^7.2.0",
|
||||
"pdf-lib": "^1.17.1",
|
||||
"sass": "^1.97.2",
|
||||
"svelte": "^5.43.5",
|
||||
"tslib": "2.4.0",
|
||||
"typescript": "4.7.4"
|
||||
|
|
@ -586,7 +589,6 @@
|
|||
"version": "0.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
|
||||
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.5.0",
|
||||
|
|
@ -597,7 +599,6 @@
|
|||
"version": "2.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
|
||||
"integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/gen-mapping": "^0.3.5",
|
||||
|
|
@ -608,7 +609,6 @@
|
|||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
|
|
@ -618,14 +618,12 @@
|
|||
"version": "1.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
|
||||
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.31",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
|
||||
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": "^3.1.0",
|
||||
|
|
@ -653,6 +651,15 @@
|
|||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lucide/svelte": {
|
||||
"version": "0.562.0",
|
||||
"resolved": "https://registry.npmjs.org/@lucide/svelte/-/svelte-0.562.0.tgz",
|
||||
"integrity": "sha512-wDMULwtTFN2Sc/TFBm6gfuVCNb4Y5P9LDrwxNnUbV52+IEU7NXZmvxwXoz+vrrpad6Xupq+Hw5eUlqIHEGhouw==",
|
||||
"license": "ISC",
|
||||
"peerDependencies": {
|
||||
"svelte": "^5"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
|
|
@ -688,6 +695,330 @@
|
|||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.4.tgz",
|
||||
"integrity": "sha512-WYa2tUVV5HiArWPB3ydlOc4R2ivq0IDrlqhMi3l7mVsFEXNcTfxYFPIHXHXIh/ca/y/V5N4E1zecyxdIBjYnkQ==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"detect-libc": "^2.0.3",
|
||||
"is-glob": "^4.0.3",
|
||||
"node-addon-api": "^7.0.0",
|
||||
"picomatch": "^4.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@parcel/watcher-android-arm64": "2.5.4",
|
||||
"@parcel/watcher-darwin-arm64": "2.5.4",
|
||||
"@parcel/watcher-darwin-x64": "2.5.4",
|
||||
"@parcel/watcher-freebsd-x64": "2.5.4",
|
||||
"@parcel/watcher-linux-arm-glibc": "2.5.4",
|
||||
"@parcel/watcher-linux-arm-musl": "2.5.4",
|
||||
"@parcel/watcher-linux-arm64-glibc": "2.5.4",
|
||||
"@parcel/watcher-linux-arm64-musl": "2.5.4",
|
||||
"@parcel/watcher-linux-x64-glibc": "2.5.4",
|
||||
"@parcel/watcher-linux-x64-musl": "2.5.4",
|
||||
"@parcel/watcher-win32-arm64": "2.5.4",
|
||||
"@parcel/watcher-win32-ia32": "2.5.4",
|
||||
"@parcel/watcher-win32-x64": "2.5.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-android-arm64": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.4.tgz",
|
||||
"integrity": "sha512-hoh0vx4v+b3BNI7Cjoy2/B0ARqcwVNrzN/n7DLq9ZB4I3lrsvhrkCViJyfTj/Qi5xM9YFiH4AmHGK6pgH1ss7g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-darwin-arm64": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.4.tgz",
|
||||
"integrity": "sha512-kphKy377pZiWpAOyTgQYPE5/XEKVMaj6VUjKT5VkNyUJlr2qZAn8gIc7CPzx+kbhvqHDT9d7EqdOqRXT6vk0zw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-darwin-x64": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.4.tgz",
|
||||
"integrity": "sha512-UKaQFhCtNJW1A9YyVz3Ju7ydf6QgrpNQfRZ35wNKUhTQ3dxJ/3MULXN5JN/0Z80V/KUBDGa3RZaKq1EQT2a2gg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-freebsd-x64": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.4.tgz",
|
||||
"integrity": "sha512-Dib0Wv3Ow/m2/ttvLdeI2DBXloO7t3Z0oCp4bAb2aqyqOjKPPGrg10pMJJAQ7tt8P4V2rwYwywkDhUia/FgS+Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-arm-glibc": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.4.tgz",
|
||||
"integrity": "sha512-I5Vb769pdf7Q7Sf4KNy8Pogl/URRCKu9ImMmnVKYayhynuyGYMzuI4UOWnegQNa2sGpsPSbzDsqbHNMyeyPCgw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-arm-musl": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.4.tgz",
|
||||
"integrity": "sha512-kGO8RPvVrcAotV4QcWh8kZuHr9bXi9a3bSZw7kFarYR0+fGliU7hd/zevhjw8fnvIKG3J9EO5G6sXNGCSNMYPQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-arm64-glibc": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.4.tgz",
|
||||
"integrity": "sha512-KU75aooXhqGFY2W5/p8DYYHt4hrjHZod8AhcGAmhzPn/etTa+lYCDB2b1sJy3sWJ8ahFVTdy+EbqSBvMx3iFlw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-arm64-musl": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.4.tgz",
|
||||
"integrity": "sha512-Qx8uNiIekVutnzbVdrgSanM+cbpDD3boB1f8vMtnuG5Zau4/bdDbXyKwIn0ToqFhIuob73bcxV9NwRm04/hzHQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-x64-glibc": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.4.tgz",
|
||||
"integrity": "sha512-UYBQvhYmgAv61LNUn24qGQdjtycFBKSK3EXr72DbJqX9aaLbtCOO8+1SkKhD/GNiJ97ExgcHBrukcYhVjrnogA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-x64-musl": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.4.tgz",
|
||||
"integrity": "sha512-YoRWCVgxv8akZrMhdyVi6/TyoeeMkQ0PGGOf2E4omODrvd1wxniXP+DBynKoHryStks7l+fDAMUBRzqNHrVOpg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-win32-arm64": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.4.tgz",
|
||||
"integrity": "sha512-iby+D/YNXWkiQNYcIhg8P5hSjzXEHaQrk2SLrWOUD7VeC4Ohu0WQvmV+HDJokZVJ2UjJ4AGXW3bx7Lls9Ln4TQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-win32-ia32": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.4.tgz",
|
||||
"integrity": "sha512-vQN+KIReG0a2ZDpVv8cgddlf67J8hk1WfZMMP7sMeZmJRSmEax5xNDNWKdgqSe2brOKTQQAs3aCCUal2qBHAyg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-win32-x64": {
|
||||
"version": "2.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.4.tgz",
|
||||
"integrity": "sha512-3A6efb6BOKwyw7yk9ro2vus2YTt2nvcd56AuzxdMiVOxL9umDyN5PKkKfZ/gZ9row41SjVmTVQNWQhaRRGpOKw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher/node_modules/picomatch": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/@pdf-lib/standard-fonts": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz",
|
||||
|
|
@ -712,7 +1043,6 @@
|
|||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.6.tgz",
|
||||
"integrity": "sha512-4awhxtMh4cx9blePWl10HRHj8Iivtqj+2QdDCSMDzxG+XKa9+VCNupQuCuvzEhYPzZSrX+0gC+0lHA/0fFKKQQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"acorn": "^8.9.0"
|
||||
|
|
@ -741,7 +1071,6 @@
|
|||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
|
|
@ -953,7 +1282,6 @@
|
|||
"version": "8.15.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
|
|
@ -1026,7 +1354,6 @@
|
|||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
|
||||
"integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
|
|
@ -1045,7 +1372,6 @@
|
|||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
|
||||
"integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
|
|
@ -1122,11 +1448,26 @@
|
|||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
|
||||
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"readdirp": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14.16.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/clsx": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
|
|
@ -1214,6 +1555,17 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
||||
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/dir-glob": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
||||
|
|
@ -1289,6 +1641,23 @@
|
|||
"find-cache-dir": "^3.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-svelte": {
|
||||
"version": "0.9.4",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-svelte/-/esbuild-svelte-0.9.4.tgz",
|
||||
"integrity": "sha512-v/a0GjkKN06nal2QLluxjk2GXsei3fdtjIuHRa6pVnri5rQBZ6pj4a2WwjLfRojgRsLwDHl4xSeZ1BeUHsqQrw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/trace-mapping": "^0.3.19"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"esbuild": ">=0.17.0",
|
||||
"svelte": ">=4.2.1 <6"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-string-regexp": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||
|
|
@ -1440,7 +1809,6 @@
|
|||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz",
|
||||
"integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/espree": {
|
||||
|
|
@ -1488,7 +1856,6 @@
|
|||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/esrap/-/esrap-2.1.2.tgz",
|
||||
"integrity": "sha512-DgvlIQeowRNyvLPWW4PT7Gu13WznY288Du086E751mwwbsgr29ytBiYeLzAGIo0qk3Ujob0SDk8TiSaM5WQzNg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.4.15"
|
||||
|
|
@ -1790,6 +2157,13 @@
|
|||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/immutable": {
|
||||
"version": "5.1.4",
|
||||
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz",
|
||||
"integrity": "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/import-fresh": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||
|
|
@ -1880,7 +2254,6 @@
|
|||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
|
||||
"integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "^1.0.6"
|
||||
|
|
@ -1955,7 +2328,6 @@
|
|||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
|
||||
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/locate-path": {
|
||||
|
|
@ -1997,7 +2369,6 @@
|
|||
"version": "0.30.21",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
|
||||
"integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.5.5"
|
||||
|
|
@ -2088,6 +2459,14 @@
|
|||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/node-addon-api": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
|
||||
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/obsidian": {
|
||||
"version": "1.4.11",
|
||||
"resolved": "https://registry.npmjs.org/obsidian/-/obsidian-1.4.11.tgz",
|
||||
|
|
@ -2389,6 +2768,20 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
||||
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 14.18.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/regexpp": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
|
||||
|
|
@ -2460,6 +2853,27 @@
|
|||
"queue-microtask": "^1.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/sass": {
|
||||
"version": "1.97.2",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.97.2.tgz",
|
||||
"integrity": "sha512-y5LWb0IlbO4e97Zr7c3mlpabcbBtS+ieiZ9iwDooShpFKWXf62zz5pEPdwrLYm+Bxn1fnbwFGzHuCLSA9tBmrw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chokidar": "^4.0.0",
|
||||
"immutable": "^5.0.2",
|
||||
"source-map-js": ">=0.6.2 <2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"sass": "sass.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@parcel/watcher": "^2.4.1"
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
|
|
@ -2512,6 +2926,16 @@
|
|||
"resolved": "https://registry.npmjs.org/sorted-btree/-/sorted-btree-1.8.1.tgz",
|
||||
"integrity": "sha512-395+XIP+wqNn3USkFSrNz7G3Ss/MXlZEqesxvzCRFwL14h6e8LukDHdLBePn5pwbm5OQ9vGu8mDyz2lLDIqamQ=="
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
|
|
@ -2560,7 +2984,6 @@
|
|||
"version": "5.43.5",
|
||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.43.5.tgz",
|
||||
"integrity": "sha512-HQoZArIewxQVNedseDsgMgnRSC4XOXczxXLF9rOJaPIJkg58INOPUiL8aEtzqZIXNSZJyw8NmqObwg/voajiHQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/remapping": "^2.3.4",
|
||||
|
|
@ -2729,7 +3152,6 @@
|
|||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz",
|
||||
"integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
11
package.json
11
package.json
|
|
@ -4,10 +4,10 @@
|
|||
"description": "An Obsidian.md plugin that provides a powerful indexing & referencing system for theorems & equations in your vault. Bring LaTeX-like workflow into Obsidian with theorem environments, automatic equation numbering, and more.",
|
||||
"scripts": {
|
||||
"dev": "node esbuild.config.mjs",
|
||||
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production && sass styles.scss styles.css",
|
||||
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production && sass src/styles/main.css styles.css",
|
||||
"prod": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
|
||||
"dev-style": "sass --watch styles.scss styles.css",
|
||||
"build-style": "sass --watch styles.scss styles.css",
|
||||
"dev-style": "sass --watch src/styles/main.css styles.css",
|
||||
"build-style": "sass --watch src/styles/main.css styles.css",
|
||||
"version": "node version-bump.mjs && git add manifest.json versions.json"
|
||||
},
|
||||
"keywords": [],
|
||||
|
|
@ -20,9 +20,11 @@
|
|||
"@typescript-eslint/parser": "5.29.0",
|
||||
"builtin-modules": "3.3.0",
|
||||
"deepmerge": "^4.3.1",
|
||||
"esbuild-svelte": "^0.9.4",
|
||||
"obsidian": "latest",
|
||||
"p-limit": "^7.2.0",
|
||||
"pdf-lib": "^1.17.1",
|
||||
"sass": "^1.97.2",
|
||||
"svelte": "^5.43.5",
|
||||
"tslib": "2.4.0",
|
||||
"typescript": "4.7.4"
|
||||
|
|
@ -30,10 +32,11 @@
|
|||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@lezer/common": "^1.0.3",
|
||||
"@lucide/svelte": "^0.562.0",
|
||||
"esbuild": "^0.25.12",
|
||||
"esbuild-plugin-inline-worker": "^0.1.1",
|
||||
"flatqueue": "^2.0.3",
|
||||
"monkey-around": "^2.3.0",
|
||||
"sorted-btree": "^1.8.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
6
src/features/cache/equation-cache.ts
vendored
6
src/features/cache/equation-cache.ts
vendored
|
|
@ -6,7 +6,7 @@ import { processActiveNoteEquations } from 'features/equations/numbering';
|
|||
export class EquationCache {
|
||||
private cache: Map<string, Map<string, EquationBlock>> = new Map();
|
||||
|
||||
constructor(private plugin: LatexReferencer) {}
|
||||
constructor(private plugin: LatexReferencer) { }
|
||||
|
||||
/**
|
||||
* Synchronously gets a cached equation block for a given file path and block ID.
|
||||
|
|
@ -18,6 +18,10 @@ export class EquationCache {
|
|||
return this.cache.get(filePath)?.get(blockId);
|
||||
}
|
||||
|
||||
getEquationsForFile(filePath: string): Map<string, EquationBlock> | undefined {
|
||||
return this.cache.get(filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously reads a file, processes its equations, and updates the cache.
|
||||
* @param file The file to process.
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { EditorView, ViewPlugin, ViewUpdate } from '@codemirror/view';
|
|||
import { editorInfoField } from 'obsidian';
|
||||
import LatexReferencer from 'main';
|
||||
import { CONVERTER, getEqNumberPrefix } from 'utils/format';
|
||||
import type { PluginSettings } from "features/settings/settings";
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -122,7 +123,7 @@ function parseEquationInfo(state: EditorState, plugin: LatexReferencer): Equatio
|
|||
}
|
||||
|
||||
let equationCount = 0;
|
||||
const eqPrefix = getEqNumberPrefix(plugin.app, file, settings);
|
||||
const eqPrefix = getEqNumberPrefix(plugin.app, file, settings as Required<PluginSettings>);
|
||||
const eqSuffix = settings.eqNumberSuffix;
|
||||
|
||||
for (const info of equationInfos) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { CONVERTER, getEqNumberPrefix } from "utils/format";
|
|||
import { EquationBlock } from "types";
|
||||
import LatexReferencer from "main";
|
||||
import { ActiveNoteEquationProvider } from "features/equations/provider-equation";
|
||||
import type { PluginSettings } from "features/settings/settings";
|
||||
|
||||
interface ReferenceInfo {
|
||||
totalCount: number;
|
||||
|
|
@ -28,7 +29,7 @@ export function processActiveNoteEquations(plugin: LatexReferencer, file: TFile,
|
|||
if (!referenceMap.has(baseId)) {
|
||||
referenceMap.set(baseId, { totalCount: 0, subIndices: new Set() });
|
||||
}
|
||||
const refInfo = referenceMap.get(baseId)!;
|
||||
const refInfo = referenceMap.get(baseId) ?? { totalCount: 0, subIndices: new Set() };
|
||||
|
||||
refInfo.totalCount++;
|
||||
if (subIndexStr) {
|
||||
|
|
@ -41,7 +42,7 @@ export function processActiveNoteEquations(plugin: LatexReferencer, file: TFile,
|
|||
|
||||
const processedEquations = new Map<string, EquationBlock>();
|
||||
let equationCount = 0;
|
||||
const eqPrefix = getEqNumberPrefix(plugin.app, file, settings);
|
||||
const eqPrefix = getEqNumberPrefix(plugin.app, file, settings as Required<PluginSettings>);
|
||||
const eqSuffix = settings.eqNumberSuffix;
|
||||
|
||||
// 2. Process each equation using the pre-computed reference map.
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
export default {
|
||||
exportCurrentFile: "Export current file to PDF",
|
||||
exportCurrentFileWithPrevious: "Export to PDF with previous Settings",
|
||||
exportDialog: {
|
||||
filenameAsTitle: "Include file name as title",
|
||||
pageSize: "Page Size",
|
||||
margin: "Margin",
|
||||
downscalePercent: "Downscale Percent",
|
||||
landscape: "Landscape",
|
||||
displayHeader: "Display Header",
|
||||
displayFooter: "Display Footer",
|
||||
openAfterExport: "Open after export",
|
||||
cssSnippets: "CSS snippets",
|
||||
},
|
||||
settings: {
|
||||
showTitle: "Add file name as title",
|
||||
displayHeader: "Display headers",
|
||||
displayFooter: "Display footer",
|
||||
printBackground: "Print background",
|
||||
maxLevel: "Max headings level of the outline",
|
||||
displayMetadata: "PDF metadata",
|
||||
headerTemplate: "Header Template",
|
||||
footerTemplate: "Footer Template",
|
||||
isTimestamp: "Add timestamp",
|
||||
enabledCss: "Enable select css snippets",
|
||||
concurrency: "Limit concurrency",
|
||||
debugMode: "Debug Mode",
|
||||
},
|
||||
};
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
import * as merge from "deepmerge";
|
||||
import en from "./en";
|
||||
import zh from "./zh";
|
||||
|
||||
export type Lang = typeof en;
|
||||
|
||||
export default {
|
||||
i18n: {
|
||||
en,
|
||||
zh,
|
||||
},
|
||||
get current() {
|
||||
const lang = window.localStorage.getItem("language") ?? "en";
|
||||
return merge(this.i18n.en, this.i18n[lang] ?? {}) as Lang;
|
||||
},
|
||||
};
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
import type { Lang } from ".";
|
||||
|
||||
export default {
|
||||
exportCurrentFile: "导出当前文件为PDF",
|
||||
exportCurrentFileWithPrevious: "使用上一次设置导出为PDF",
|
||||
|
||||
exportDialog: {
|
||||
filenameAsTitle: "将笔记名作为标题",
|
||||
pageSize: "纸张尺寸",
|
||||
margin: "页边距",
|
||||
downscalePercent: "缩放",
|
||||
landscape: "横向打印",
|
||||
displayHeader: "页眉",
|
||||
displayFooter: "页脚",
|
||||
openAfterExport: "导出后打开",
|
||||
cssSnippets: "CSS代码片段",
|
||||
},
|
||||
|
||||
settings: {
|
||||
showTitle: "将笔记名作为标题",
|
||||
displayHeader: "显示页眉",
|
||||
displayFooter: "显示页脚",
|
||||
printBackground: "打印背景",
|
||||
maxLevel: "最大标题级别",
|
||||
displayMetadata: "PDF元数据",
|
||||
headerTemplate: "页眉模板",
|
||||
footerTemplate: "页脚模板",
|
||||
isTimestamp: "文件名添加时间戳",
|
||||
enabledCss: "启用CSS片段选择",
|
||||
concurrency: "限制并发数",
|
||||
debugMode: "调试模式",
|
||||
},
|
||||
}
|
||||
|
|
@ -1,223 +0,0 @@
|
|||
import { App, MarkdownView, Menu, Plugin, type PluginManifest, TFile, TFolder } from "obsidian";
|
||||
import i18n, { type Lang } from "./i18n";
|
||||
import { ExportConfigModal, type TConfig } from "./modal";
|
||||
import ConfigSettingTab from "./setting";
|
||||
import { traverseFolder } from "./utils";
|
||||
import * as fs from "fs/promises";
|
||||
import * as path from "path";
|
||||
|
||||
const isDev = process.env.NODE_ENV === "development";
|
||||
|
||||
export interface BetterExportPdfPluginSettings {
|
||||
prevConfig?: TConfig;
|
||||
|
||||
showTitle: boolean;
|
||||
maxLevel: string;
|
||||
|
||||
displayHeader: boolean;
|
||||
displayFooter: boolean;
|
||||
headerTemplate: string;
|
||||
footerTemplate: string;
|
||||
|
||||
printBackground: boolean;
|
||||
generateTaggedPDF: boolean;
|
||||
|
||||
displayMetadata: boolean;
|
||||
|
||||
isTimestamp: boolean;
|
||||
debug: boolean;
|
||||
enabledCss: boolean;
|
||||
concurrency: string;
|
||||
}
|
||||
|
||||
const DEFAULT_SETTINGS: BetterExportPdfPluginSettings = {
|
||||
showTitle: true,
|
||||
maxLevel: "6",
|
||||
|
||||
displayHeader: true,
|
||||
displayFooter: true,
|
||||
headerTemplate: `<div style="width: 100vw;font-size:10px;text-align:center;"><span class="title"></span></div>`,
|
||||
footerTemplate: `<div style="width: 100vw;font-size:10px;text-align:center;"><span class="pageNumber"></span> / <span class="totalPages"></span></div>`,
|
||||
|
||||
printBackground: false,
|
||||
generateTaggedPDF: false,
|
||||
|
||||
displayMetadata: false,
|
||||
debug: false,
|
||||
isTimestamp: false,
|
||||
enabledCss: false,
|
||||
concurrency: "5",
|
||||
};
|
||||
|
||||
export default class BetterExportPdfPlugin extends Plugin {
|
||||
settings: BetterExportPdfPluginSettings;
|
||||
i18n: Lang;
|
||||
|
||||
constructor(app: App, manifest: PluginManifest) {
|
||||
super(app, manifest);
|
||||
this.i18n = i18n.current;
|
||||
}
|
||||
|
||||
async onload() {
|
||||
await this.loadSettings();
|
||||
|
||||
this.registerCommand();
|
||||
this.registerSetting();
|
||||
this.registerEvents();
|
||||
}
|
||||
|
||||
registerCommand() {
|
||||
this.addCommand({
|
||||
id: "export-current-file-to-pdf",
|
||||
name: this.i18n.exportCurrentFile,
|
||||
checkCallback: (checking: boolean) => {
|
||||
const view = this.app.workspace.getActiveViewOfType(MarkdownView);
|
||||
const file = view?.file;
|
||||
if (!file) {
|
||||
return false;
|
||||
}
|
||||
if (checking) {
|
||||
return true;
|
||||
}
|
||||
new ExportConfigModal(this, file).open();
|
||||
|
||||
return true;
|
||||
},
|
||||
});
|
||||
// this.addCommand({
|
||||
// id: "better-export-pdf:with-prev-setting",
|
||||
// name: this.i18n.exportCurrentFileWithPrevious,
|
||||
// checkCallback: (checking: boolean) => {
|
||||
// const view = this.app.workspace.getActiveViewOfType(MarkdownView);
|
||||
// const file = view?.file;
|
||||
// if (!file) {
|
||||
// return false;
|
||||
// }
|
||||
// if (checking) {
|
||||
// return true;
|
||||
// }
|
||||
// new ExportConfigModal(this, file, this.settings?.prevConfig).open();
|
||||
|
||||
// return true;
|
||||
// },
|
||||
// });
|
||||
}
|
||||
|
||||
registerSetting() {
|
||||
// This adds a settings tab so the user can configure various aspects of the plugin
|
||||
this.addSettingTab(new ConfigSettingTab(this.app, this));
|
||||
}
|
||||
|
||||
registerEvents() {
|
||||
// Register the Export As HTML button in the file menu
|
||||
this.registerEvent(
|
||||
this.app.workspace.on("file-menu", (menu, file: TFile | TFolder) => {
|
||||
let title = file instanceof TFolder ? "Export folder to PDF" : "Better Export PDF";
|
||||
if (isDev) {
|
||||
title = `${title} (dev)`;
|
||||
}
|
||||
|
||||
menu.addItem((item) => {
|
||||
item
|
||||
.setTitle(title)
|
||||
.setIcon("download")
|
||||
.setSection("action")
|
||||
.onClick(async () => {
|
||||
new ExportConfigModal(this, file).open();
|
||||
});
|
||||
});
|
||||
}),
|
||||
);
|
||||
this.registerEvent(
|
||||
this.app.workspace.on("file-menu", (menu, file: TFile | TFolder) => {
|
||||
if (file instanceof TFolder) {
|
||||
let title = "Export to PDF...";
|
||||
if (isDev) {
|
||||
title = `${title} (dev)`;
|
||||
}
|
||||
menu.addItem((item) => {
|
||||
item.setTitle(title).setIcon("lucide-folder-down").setSection("action");
|
||||
// @ts-ignore
|
||||
const subMenu: Menu = item.setSubmenu();
|
||||
subMenu.addItem((item) =>
|
||||
item
|
||||
.setTitle("Export each file to PDF")
|
||||
.setIcon("lucide-file-stack")
|
||||
.onClick(async () => {
|
||||
new ExportConfigModal(this, file, true).open();
|
||||
}),
|
||||
);
|
||||
subMenu.addItem((item) =>
|
||||
item
|
||||
.setTitle("Generate TOC.md file")
|
||||
.setIcon("lucide-file-text")
|
||||
.onClick(async () => {
|
||||
await this.generateToc(file);
|
||||
}),
|
||||
);
|
||||
});
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async generateToc(root: TFolder | TFile) {
|
||||
// @ts-ignore
|
||||
const basePath = this.app.vault.adapter.basePath;
|
||||
const toc = path.join(basePath, root.path, "_TOC_.md");
|
||||
const content = `---\ntoc: true\ntitle: ${root.name}\n---\n`;
|
||||
await fs.writeFile(toc, content);
|
||||
if (root instanceof TFolder) {
|
||||
const files = traverseFolder(root);
|
||||
for (const file of files) {
|
||||
if (file.name == "_TOC_.md") {
|
||||
continue;
|
||||
}
|
||||
await fs.appendFile(toc, `[[${file.path}]]\n`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onunload() {}
|
||||
async loadSettings() {
|
||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
||||
}
|
||||
|
||||
async saveSettings() {
|
||||
await this.saveData(this.settings);
|
||||
}
|
||||
|
||||
changeConfig() {
|
||||
// @ts-ignore
|
||||
const theme = "obsidian" === this.app.vault?.getConfig("theme");
|
||||
if (theme) {
|
||||
document.body.addClass("theme-light");
|
||||
document.body.removeClass("theme-dark");
|
||||
}
|
||||
document.body.removeClass("theme-dark");
|
||||
const node = document.body.createDiv("print");
|
||||
|
||||
const reset = function () {
|
||||
node.detach();
|
||||
if (theme) {
|
||||
document.body.removeClass("theme-light");
|
||||
document.body.addClass("theme-dark");
|
||||
}
|
||||
// t.hide();
|
||||
};
|
||||
node.addEventListener("click", reset);
|
||||
|
||||
const el = document.body.createDiv("print");
|
||||
|
||||
const el2 = el.createDiv("markdown-preview-view markdown-rendered");
|
||||
|
||||
// @ts-ignore
|
||||
el2.toggleClass("rtl", this.app.vault.getConfig("rightToLeft"));
|
||||
// @ts-ignore
|
||||
el2.toggleClass("show-frontmatter", this.app.vault.getConfig("showFrontmatter"));
|
||||
|
||||
el2.createEl("h1", {
|
||||
text: "xxxxx", // a.basename
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,8 @@
|
|||
import * as electron from "electron";
|
||||
import * as fs from "fs/promises";
|
||||
import { ButtonComponent, type FrontMatterCache, Modal, Setting, TFile, TFolder, debounce } from "obsidian";
|
||||
import * as path from "path";
|
||||
import { PageSize } from "./constant";
|
||||
import i18n, { type Lang } from "./i18n";
|
||||
import BetterExportPdfPlugin from "./main";
|
||||
import LatexReferencer from "../../main";
|
||||
import { exportToPDF, getOutputFile, getOutputPath } from "./pdf";
|
||||
import { createWebview, fixDoc, getAllStyles, getPatchStyle, renderMarkdown, type ParamType } from "./render";
|
||||
import { isNumber, mm2px, px2mm, safeParseFloat, safeParseInt, traverseFolder } from "./utils";
|
||||
|
|
@ -53,7 +51,6 @@ export class ExportConfigModal extends Modal {
|
|||
canceled: boolean;
|
||||
multiplePdf?: boolean;
|
||||
callback: Callback;
|
||||
plugin: BetterExportPdfPlugin;
|
||||
file: TFile | TFolder;
|
||||
preview: Electron.WebViewElement;
|
||||
webviews: Electron.WebViewElement[];
|
||||
|
|
@ -62,18 +59,15 @@ export class ExportConfigModal extends Modal {
|
|||
docs: DocType[];
|
||||
title: string;
|
||||
frontMatter: FrontMatterCache;
|
||||
i18n: Lang;
|
||||
scale: number;
|
||||
// @ts-ignore
|
||||
svelte: Progress;
|
||||
|
||||
constructor(plugin: BetterExportPdfPlugin, file: TFile | TFolder, multiplePdf?: boolean) {
|
||||
constructor(public plugin: LatexReferencer, file: TFile | TFolder, multiplePdf?: boolean) {
|
||||
super(plugin.app);
|
||||
this.canceled = true;
|
||||
this.plugin = plugin;
|
||||
this.file = file;
|
||||
this.completed = false;
|
||||
this.i18n = i18n.current;
|
||||
this.docs = [];
|
||||
this.scale = 0.75;
|
||||
this.webviews = [];
|
||||
|
|
@ -410,7 +404,7 @@ export class ExportConfigModal extends Modal {
|
|||
}
|
||||
|
||||
private generateForm(contentEl: HTMLDivElement) {
|
||||
new Setting(contentEl).setName(this.i18n.exportDialog.filenameAsTitle).addToggle((toggle) =>
|
||||
new Setting(contentEl).setName("Include file name as title").addToggle((toggle) =>
|
||||
toggle
|
||||
.setTooltip("Include file name as title")
|
||||
.setValue(this.config["showTitle"])
|
||||
|
|
@ -444,7 +438,7 @@ export class ExportConfigModal extends Modal {
|
|||
"Ledger",
|
||||
"Custom",
|
||||
];
|
||||
new Setting(contentEl).setName(this.i18n.exportDialog.pageSize).addDropdown((dropdown) => {
|
||||
new Setting(contentEl).setName("Page Size").addDropdown((dropdown) => {
|
||||
dropdown
|
||||
.addOptions(Object.fromEntries(pageSizes.map((size) => [size, size])))
|
||||
.setValue(this.config.pageSize as string)
|
||||
|
|
@ -493,7 +487,7 @@ export class ExportConfigModal extends Modal {
|
|||
sizeEl.settingEl.hidden = this.config["pageSize"] !== "Custom";
|
||||
|
||||
new Setting(contentEl)
|
||||
.setName(this.i18n.exportDialog.margin)
|
||||
.setName("Margin")
|
||||
.setDesc("The unit is millimeters.")
|
||||
.addDropdown((dropdown) => {
|
||||
dropdown
|
||||
|
|
@ -557,7 +551,7 @@ export class ExportConfigModal extends Modal {
|
|||
});
|
||||
btmEl.settingEl.hidden = this.config["marginType"] != "3";
|
||||
|
||||
new Setting(contentEl).setName(this.i18n.exportDialog.downscalePercent).addSlider((slider) => {
|
||||
new Setting(contentEl).setName("Downscale Percent").addSlider((slider) => {
|
||||
slider
|
||||
.setLimits(0, 100, 1)
|
||||
.setValue(this.config["scale"] as number)
|
||||
|
|
@ -566,7 +560,7 @@ export class ExportConfigModal extends Modal {
|
|||
slider.showTooltip();
|
||||
});
|
||||
});
|
||||
new Setting(contentEl).setName(this.i18n.exportDialog.landscape).addToggle((toggle) =>
|
||||
new Setting(contentEl).setName("Landscape").addToggle((toggle) =>
|
||||
toggle
|
||||
.setTooltip("landscape")
|
||||
.setValue(this.config["landscape"])
|
||||
|
|
@ -575,7 +569,7 @@ export class ExportConfigModal extends Modal {
|
|||
}),
|
||||
);
|
||||
|
||||
new Setting(contentEl).setName(this.i18n.exportDialog.displayHeader).addToggle((toggle) =>
|
||||
new Setting(contentEl).setName("Display Header").addToggle((toggle) =>
|
||||
toggle
|
||||
.setTooltip("Display header")
|
||||
.setValue(this.config["displayHeader"])
|
||||
|
|
@ -584,7 +578,7 @@ export class ExportConfigModal extends Modal {
|
|||
}),
|
||||
);
|
||||
|
||||
new Setting(contentEl).setName(this.i18n.exportDialog.displayFooter).addToggle((toggle) =>
|
||||
new Setting(contentEl).setName("Display Footer").addToggle((toggle) =>
|
||||
toggle
|
||||
.setTooltip("Display footer")
|
||||
.setValue(this.config["displayFooter"])
|
||||
|
|
@ -593,7 +587,7 @@ export class ExportConfigModal extends Modal {
|
|||
}),
|
||||
);
|
||||
|
||||
new Setting(contentEl).setName(this.i18n.exportDialog.openAfterExport).addToggle((toggle) =>
|
||||
new Setting(contentEl).setName("Open after export").addToggle((toggle) =>
|
||||
toggle
|
||||
.setTooltip("Open the exported file after exporting.")
|
||||
.setValue(this.config["open"])
|
||||
|
|
@ -605,7 +599,7 @@ export class ExportConfigModal extends Modal {
|
|||
const snippets = this.cssSnippets();
|
||||
|
||||
if (Object.keys(snippets).length > 0 && this.plugin.settings.enabledCss) {
|
||||
new Setting(contentEl).setName(this.i18n.exportDialog.cssSnippets).addDropdown((dropdown) => {
|
||||
new Setting(contentEl).setName("CSS snippets").addDropdown((dropdown) => {
|
||||
dropdown
|
||||
.addOption("0", "Not select")
|
||||
.addOptions(snippets)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import * as electron from "electron";
|
||||
import * as fs from "fs/promises";
|
||||
import { type FrontMatterCache } from "obsidian";
|
||||
import { type FrontMatterCache, Notice } from "obsidian";
|
||||
import { PDFArray, PDFDict, PDFDocument, PDFHexString, PDFName, PDFRef, StandardFonts } from "pdf-lib";
|
||||
|
||||
import type { BetterExportPdfPluginSettings } from "./main";
|
||||
import type { PluginSettings } from "../settings/settings";
|
||||
|
||||
import type { DocType, PageSizeType, TConfig } from "./modal";
|
||||
import { TreeNode, getHeadingTree, safeParseFloat, safeParseInt } from "./utils";
|
||||
|
||||
|
|
@ -261,9 +262,9 @@ export const setOutline = async (doc: PDFDocument, outlines: readonly PDFOutline
|
|||
Type: "Outlines",
|
||||
...(rootCount > 0
|
||||
? {
|
||||
First: refMap.get(outlines[0])!,
|
||||
Last: refMap.get(outlines[outlines.length - 1])!,
|
||||
}
|
||||
First: refMap.get(outlines[0])!,
|
||||
Last: refMap.get(outlines[outlines.length - 1])!,
|
||||
}
|
||||
: {}),
|
||||
Count: rootCount,
|
||||
}),
|
||||
|
|
@ -367,7 +368,7 @@ export function setMetadata(
|
|||
|
||||
export async function exportToPDF(
|
||||
outputFile: string,
|
||||
config: TConfig & BetterExportPdfPluginSettings,
|
||||
config: TConfig & PluginSettings, // Changed from BetterExportPdfPluginSettings
|
||||
w: Electron.WebViewElement,
|
||||
{ doc, frontMatter }: DocType,
|
||||
) {
|
||||
|
|
@ -434,12 +435,8 @@ export async function exportToPDF(
|
|||
}
|
||||
|
||||
try {
|
||||
let data: Uint8Array = await new Promise<Buffer>((resolve, reject) => {
|
||||
(w as any).printToPDF(printOptions, (error: any, data: Buffer) => {
|
||||
if (error) return reject(error);
|
||||
resolve(data);
|
||||
});
|
||||
});
|
||||
const buffer = await (w as any).printToPDF(printOptions);
|
||||
let data: Uint8Array = new Uint8Array(buffer);
|
||||
|
||||
data = await editPDF(data, {
|
||||
headings: getHeadingTree(doc),
|
||||
|
|
@ -456,6 +453,7 @@ export async function exportToPDF(
|
|||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
new Notice("Export to PDF failed: " + error);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,192 +0,0 @@
|
|||
import { App, PluginSettingTab, Setting, TextAreaComponent } from "obsidian";
|
||||
import i18n, { type Lang } from "./i18n";
|
||||
import BetterExportPdfPlugin from "./main";
|
||||
|
||||
function setAttributes(element: HTMLTextAreaElement, attributes: { [x: string]: string }) {
|
||||
for (const key in attributes) {
|
||||
element.setAttribute(key, attributes[key]);
|
||||
}
|
||||
}
|
||||
|
||||
export const renderBuyMeACoffeeBadge = (contentEl: HTMLElement | DocumentFragment, width = 175) => {
|
||||
const linkEl = contentEl.createEl("a", {
|
||||
href: "https://www.buymeacoffee.com/l1xnan",
|
||||
});
|
||||
const imgEl = linkEl.createEl("img");
|
||||
imgEl.src =
|
||||
"https://img.buymeacoffee.com/button-api/?text=Buy me a coffee&emoji=&slug=nathangeorge&button_colour=6a8696&font_colour=ffffff&font_family=Poppins&outline_colour=000000&coffee_colour=FFDD00";
|
||||
imgEl.alt = "Buy me a coffee";
|
||||
imgEl.width = width;
|
||||
};
|
||||
|
||||
export default class ConfigSettingTab extends PluginSettingTab {
|
||||
plugin: BetterExportPdfPlugin;
|
||||
i18n: Lang;
|
||||
|
||||
constructor(app: App, plugin: BetterExportPdfPlugin) {
|
||||
super(app, plugin);
|
||||
this.plugin = plugin;
|
||||
this.i18n = i18n.current;
|
||||
}
|
||||
|
||||
display(): void {
|
||||
const { containerEl } = this;
|
||||
|
||||
containerEl.empty();
|
||||
|
||||
const supportDesc = new DocumentFragment();
|
||||
supportDesc.createDiv({
|
||||
text: "Support the continued development of this plugin.",
|
||||
});
|
||||
new Setting(containerEl).setDesc(supportDesc);
|
||||
renderBuyMeACoffeeBadge(containerEl);
|
||||
|
||||
new Setting(containerEl).setName(this.i18n.settings.showTitle).addToggle((toggle) =>
|
||||
toggle
|
||||
.setTooltip(this.i18n.settings.showTitle)
|
||||
.setValue(this.plugin.settings.showTitle)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.showTitle = value;
|
||||
this.plugin.saveSettings();
|
||||
}),
|
||||
);
|
||||
new Setting(containerEl).setName(this.i18n.settings.displayHeader).addToggle((toggle) =>
|
||||
toggle
|
||||
.setTooltip("Display header")
|
||||
.setValue(this.plugin.settings.displayHeader)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.displayHeader = value;
|
||||
this.plugin.saveSettings();
|
||||
}),
|
||||
);
|
||||
new Setting(containerEl).setName(this.i18n.settings.displayFooter).addToggle((toggle) =>
|
||||
toggle
|
||||
.setTooltip("Display footer")
|
||||
.setValue(this.plugin.settings.displayFooter)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.displayFooter = value;
|
||||
this.plugin.saveSettings();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(this.i18n.settings.printBackground)
|
||||
.setDesc("Whether to print background graphics")
|
||||
.addToggle((toggle) =>
|
||||
toggle.setValue(this.plugin.settings.printBackground).onChange(async (value) => {
|
||||
this.plugin.settings.printBackground = value;
|
||||
this.plugin.saveSettings();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Generate tagged PDF")
|
||||
.setDesc(
|
||||
"Whether or not to generate a tagged (accessible) PDF. Defaults to false. As this property is experimental, the generated PDF may not adhere fully to PDF/UA and WCAG standards.",
|
||||
)
|
||||
.addToggle((toggle) =>
|
||||
toggle.setValue(this.plugin.settings.generateTaggedPDF).onChange(async (value) => {
|
||||
this.plugin.settings.generateTaggedPDF = value;
|
||||
this.plugin.saveSettings();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl).setName(this.i18n.settings.maxLevel).addDropdown((dropdown) => {
|
||||
dropdown
|
||||
.addOptions(Object.fromEntries(["1", "2", "3", "4", "5", "6"].map((level) => [level, `h${level}`])))
|
||||
.setValue(this.plugin.settings.maxLevel)
|
||||
.onChange(async (value: string) => {
|
||||
this.plugin.settings.maxLevel = value;
|
||||
this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(this.i18n.settings.displayMetadata)
|
||||
.setDesc("Add frontMatter(title, author, keywords, subject creator, etc) to pdf metadata")
|
||||
.addToggle((toggle) =>
|
||||
toggle.setValue(this.plugin.settings.displayMetadata).onChange(async (value) => {
|
||||
this.plugin.settings.displayMetadata = value;
|
||||
this.plugin.saveSettings();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl).setName("Advanced").setHeading();
|
||||
|
||||
const headerContentAreaSetting = new Setting(containerEl);
|
||||
headerContentAreaSetting.settingEl.setAttribute("style", "display: grid; grid-template-columns: 1fr;");
|
||||
headerContentAreaSetting
|
||||
.setName(this.i18n.settings.headerTemplate)
|
||||
.setDesc(
|
||||
"HTML template for the print header. " +
|
||||
"Should be valid HTML markup with following classes used to inject printing values into them: " +
|
||||
'date (formatted print date), title (document title), url (document location), pageNumber (current page number) and totalPages (total pages in the document). For example, <span class="title"></span> would generate span containing the title.',
|
||||
);
|
||||
const hederContentArea = new TextAreaComponent(headerContentAreaSetting.controlEl);
|
||||
|
||||
setAttributes(hederContentArea.inputEl, {
|
||||
style: "margin-top: 12px; width: 100%; height: 6vh;",
|
||||
});
|
||||
hederContentArea.setValue(this.plugin.settings.headerTemplate).onChange(async (value) => {
|
||||
this.plugin.settings.headerTemplate = value;
|
||||
this.plugin.saveSettings();
|
||||
});
|
||||
|
||||
const footerContentAreaSetting = new Setting(containerEl);
|
||||
footerContentAreaSetting.settingEl.setAttribute("style", "display: grid; grid-template-columns: 1fr;");
|
||||
footerContentAreaSetting
|
||||
.setName(this.i18n.settings.footerTemplate)
|
||||
.setDesc("HTML template for the print footer. Should use the same format as the headerTemplate.");
|
||||
const footerContentArea = new TextAreaComponent(footerContentAreaSetting.controlEl);
|
||||
|
||||
setAttributes(footerContentArea.inputEl, {
|
||||
style: "margin-top: 12px; width: 100%; height: 6vh;",
|
||||
});
|
||||
footerContentArea.setValue(this.plugin.settings.footerTemplate).onChange(async (value) => {
|
||||
this.plugin.settings.footerTemplate = value;
|
||||
this.plugin.saveSettings();
|
||||
});
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(this.i18n.settings.isTimestamp)
|
||||
.setDesc("Add timestamp to output file name")
|
||||
.addToggle((cb) => {
|
||||
cb.setValue(this.plugin.settings.isTimestamp).onChange(async (value) => {
|
||||
this.plugin.settings.isTimestamp = value;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(this.i18n.settings.enabledCss)
|
||||
.setDesc("Select the css snippet that are not enabled")
|
||||
.addToggle((cb) => {
|
||||
cb.setValue(this.plugin.settings.enabledCss).onChange(async (value) => {
|
||||
this.plugin.settings.enabledCss = value;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName(this.i18n.settings.concurrency)
|
||||
.setDesc("Limit the number of concurrent renders")
|
||||
.addText((cb) => {
|
||||
const concurrency = this.plugin.settings?.concurrency;
|
||||
cb.setValue(concurrency?.length > 0 ? concurrency : "5").onChange(async (value) => {
|
||||
this.plugin.settings.concurrency = value;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(containerEl).setName("Debug").setHeading();
|
||||
new Setting(containerEl)
|
||||
.setName(this.i18n.settings.debugMode)
|
||||
.setDesc("This is useful for troubleshooting.")
|
||||
.addToggle((cb) => {
|
||||
cb.setValue(this.plugin.settings.debug).onChange(async (value) => {
|
||||
this.plugin.settings.debug = value;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -46,10 +46,11 @@ export class LatexRenderChild extends MarkdownRenderChild {
|
|||
const mathLink = getMathLink(this.plugin, this.targetLink, this.sourcePath);
|
||||
|
||||
if (mathLink) {
|
||||
// Check if the link element is still in the DOM
|
||||
const linkEl = this.containerEl.querySelector('a.internal-link');
|
||||
if (linkEl) {
|
||||
setMathLink(mathLink, linkEl as HTMLElement);
|
||||
// The containerEl is now the link element itself
|
||||
const linkEl = this.containerEl as HTMLElement;
|
||||
// Verify it's still in the DOM (though MarkdownRenderChild handles unloading)
|
||||
if (linkEl.isConnected) {
|
||||
setMathLink(mathLink, linkEl);
|
||||
}
|
||||
}
|
||||
finishRenderMath();
|
||||
|
|
@ -63,12 +64,12 @@ export const CustomMathLinksProcessor = (plugin: LatexReferencer): MarkdownPostP
|
|||
const href = link.getAttribute('data-href');
|
||||
if (href && href.contains('#^eq-')) {
|
||||
// This is one of our equation links.
|
||||
// The link is already a proper <a href> tag, so we just need to change its text.
|
||||
// Pass the specific link element as the container to scope the child correctly.
|
||||
context.addChild(
|
||||
new LatexRenderChild(element, plugin, context.sourcePath, href)
|
||||
new LatexRenderChild(link, plugin, context.sourcePath, href)
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
export {}
|
||||
export { }
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import { Modifier } from "obsidian";
|
||||
import type { TConfig } from "../export-pdf/modal";
|
||||
import { LeafArgs } from "../../declarations";
|
||||
|
||||
// Types
|
||||
|
|
@ -43,6 +44,22 @@ export interface PluginSettings {
|
|||
modifierToJump: Modifier;
|
||||
showModifierInstruction: boolean;
|
||||
suggestLeafOption: LeafOption;
|
||||
|
||||
// PDF Export Settings
|
||||
prevConfig?: TConfig;
|
||||
showTitle: boolean;
|
||||
maxLevel: string;
|
||||
displayHeader: boolean;
|
||||
displayFooter: boolean;
|
||||
headerTemplate: string;
|
||||
footerTemplate: string;
|
||||
printBackground: boolean;
|
||||
generateTaggedPDF: boolean;
|
||||
displayMetadata: boolean;
|
||||
isTimestamp: boolean;
|
||||
debug: boolean;
|
||||
enabledCss: boolean;
|
||||
concurrency: string;
|
||||
}
|
||||
|
||||
export const DEFAULT_SETTINGS: Required<PluginSettings> = {
|
||||
|
|
@ -69,4 +86,34 @@ export const DEFAULT_SETTINGS: Required<PluginSettings> = {
|
|||
modifierToJump: "Mod",
|
||||
showModifierInstruction: true,
|
||||
suggestLeafOption: "Current tab",
|
||||
|
||||
// PDF Export Settings
|
||||
prevConfig: {
|
||||
pageSize: "A4",
|
||||
marginType: "1",
|
||||
open: true,
|
||||
landscape: false,
|
||||
scale: 100,
|
||||
showTitle: true,
|
||||
displayHeader: true,
|
||||
displayFooter: true,
|
||||
marginTop: "10",
|
||||
marginBottom: "10",
|
||||
marginLeft: "10",
|
||||
marginRight: "10",
|
||||
cssSnippet: "0",
|
||||
},
|
||||
showTitle: true,
|
||||
maxLevel: "6",
|
||||
displayHeader: true,
|
||||
displayFooter: true,
|
||||
headerTemplate: `<div style="width: 100vw;font-size:10px;text-align:center;"><span class="title"></span></div>`,
|
||||
footerTemplate: `<div style="width: 100vw;font-size:10px;text-align:center;"><span class="pageNumber"></span> / <span class="totalPages"></span></div>`,
|
||||
printBackground: false,
|
||||
generateTaggedPDF: false,
|
||||
displayMetadata: false,
|
||||
isTimestamp: false,
|
||||
debug: false,
|
||||
enabledCss: false,
|
||||
concurrency: "5",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { App, PluginSettingTab, Setting } from "obsidian";
|
||||
import { App, PluginSettingTab, Setting, TextAreaComponent } from "obsidian";
|
||||
import LatexReferencer from "../../main";
|
||||
import { NUMBER_STYLES } from "./settings";
|
||||
|
||||
|
|
@ -133,5 +133,161 @@ export class MathSettingTab extends PluginSettingTab {
|
|||
await this.plugin.saveSettings();
|
||||
})
|
||||
);
|
||||
|
||||
containerEl.createEl("h2", { text: "PDF Export" });
|
||||
|
||||
new Setting(containerEl).setName("Add file name as title").addToggle((toggle) =>
|
||||
toggle
|
||||
.setTooltip("Add file name as title")
|
||||
.setValue(this.plugin.settings.showTitle)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.showTitle = value;
|
||||
this.plugin.saveSettings();
|
||||
}),
|
||||
);
|
||||
new Setting(containerEl).setName("Display headers").addToggle((toggle) =>
|
||||
toggle
|
||||
.setTooltip("Display header")
|
||||
.setValue(this.plugin.settings.displayHeader)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.displayHeader = value;
|
||||
this.plugin.saveSettings();
|
||||
}),
|
||||
);
|
||||
new Setting(containerEl).setName("Display footer").addToggle((toggle) =>
|
||||
toggle
|
||||
.setTooltip("Display footer")
|
||||
.setValue(this.plugin.settings.displayFooter)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.displayFooter = value;
|
||||
this.plugin.saveSettings();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Print background")
|
||||
.setDesc("Whether to print background graphics")
|
||||
.addToggle((toggle) =>
|
||||
toggle.setValue(this.plugin.settings.printBackground).onChange(async (value) => {
|
||||
this.plugin.settings.printBackground = value;
|
||||
this.plugin.saveSettings();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Generate tagged PDF")
|
||||
.setDesc(
|
||||
"Whether or not to generate a tagged (accessible) PDF. Defaults to false. As this property is experimental, the generated PDF may not adhere fully to PDF/UA and WCAG standards.",
|
||||
)
|
||||
.addToggle((toggle) =>
|
||||
toggle.setValue(this.plugin.settings.generateTaggedPDF).onChange(async (value) => {
|
||||
this.plugin.settings.generateTaggedPDF = value;
|
||||
this.plugin.saveSettings();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl).setName("Max headings level of the outline").addDropdown((dropdown) => {
|
||||
dropdown
|
||||
.addOptions(Object.fromEntries(["1", "2", "3", "4", "5", "6"].map((level) => [level, `h${level}`])))
|
||||
.setValue(this.plugin.settings.maxLevel)
|
||||
.onChange(async (value: string) => {
|
||||
this.plugin.settings.maxLevel = value;
|
||||
this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("PDF metadata")
|
||||
.setDesc("Add frontMatter(title, author, keywords, subject creator, etc) to pdf metadata")
|
||||
.addToggle((toggle) =>
|
||||
toggle.setValue(this.plugin.settings.displayMetadata).onChange(async (value) => {
|
||||
this.plugin.settings.displayMetadata = value;
|
||||
this.plugin.saveSettings();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl).setName("Advanced").setHeading();
|
||||
|
||||
const headerContentAreaSetting = new Setting(containerEl);
|
||||
headerContentAreaSetting.settingEl.setAttribute("style", "display: grid; grid-template-columns: 1fr;");
|
||||
headerContentAreaSetting
|
||||
.setName("Header Template")
|
||||
.setDesc(
|
||||
"HTML template for the print header. " +
|
||||
"Should be valid HTML markup with following classes used to inject printing values into them: " +
|
||||
'date (formatted print date), title (document title), url (document location), pageNumber (current page number) and totalPages (total pages in the document). For example, <span class="title"></span> would generate span containing the title.',
|
||||
);
|
||||
const hederContentArea = new TextAreaComponent(headerContentAreaSetting.controlEl);
|
||||
|
||||
setAttributes(hederContentArea.inputEl, {
|
||||
style: "margin-top: 12px; width: 100%; height: 6vh;",
|
||||
});
|
||||
hederContentArea.setValue(this.plugin.settings.headerTemplate).onChange(async (value) => {
|
||||
this.plugin.settings.headerTemplate = value;
|
||||
this.plugin.saveSettings();
|
||||
});
|
||||
|
||||
const footerContentAreaSetting = new Setting(containerEl);
|
||||
footerContentAreaSetting.settingEl.setAttribute("style", "display: grid; grid-template-columns: 1fr;");
|
||||
footerContentAreaSetting
|
||||
.setName("Footer Template")
|
||||
.setDesc("HTML template for the print footer. Should use the same format as the headerTemplate.");
|
||||
const footerContentArea = new TextAreaComponent(footerContentAreaSetting.controlEl);
|
||||
|
||||
setAttributes(footerContentArea.inputEl, {
|
||||
style: "margin-top: 12px; width: 100%; height: 6vh;",
|
||||
});
|
||||
footerContentArea.setValue(this.plugin.settings.footerTemplate).onChange(async (value) => {
|
||||
this.plugin.settings.footerTemplate = value;
|
||||
this.plugin.saveSettings();
|
||||
});
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Add timestamp to output file name")
|
||||
.setDesc("Add timestamp to output file name")
|
||||
.addToggle((cb) => {
|
||||
cb.setValue(this.plugin.settings.isTimestamp).onChange(async (value) => {
|
||||
this.plugin.settings.isTimestamp = value;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Select the css snippet that are not enabled")
|
||||
.setDesc("Select the css snippet that are not enabled")
|
||||
.addToggle((cb) => {
|
||||
cb.setValue(this.plugin.settings.enabledCss).onChange(async (value) => {
|
||||
this.plugin.settings.enabledCss = value;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Limit the number of concurrent renders")
|
||||
.setDesc("Limit the number of concurrent renders")
|
||||
.addText((cb) => {
|
||||
const concurrency = this.plugin.settings?.concurrency;
|
||||
cb.setValue(concurrency?.length > 0 ? concurrency : "5").onChange(async (value) => {
|
||||
this.plugin.settings.concurrency = value;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(containerEl).setName("Debug").setHeading();
|
||||
new Setting(containerEl)
|
||||
.setName("This is useful for troubleshooting.")
|
||||
.setDesc("This is useful for troubleshooting.")
|
||||
.addToggle((cb) => {
|
||||
cb.setValue(this.plugin.settings.debug).onChange(async (value) => {
|
||||
this.plugin.settings.debug = value;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function setAttributes(element: HTMLTextAreaElement, attributes: { [x: string]: string }) {
|
||||
for (const key in attributes) {
|
||||
element.setAttribute(key, attributes[key]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,21 +21,6 @@ export class LatexLinkProvider extends Provider {
|
|||
return null;
|
||||
}
|
||||
|
||||
let content: string | null = null;
|
||||
for (const leaf of this.app.workspace.getLeavesOfType("markdown")) {
|
||||
const view = leaf.view;
|
||||
if (view instanceof MarkdownView && view.file?.path === targetFile.path) {
|
||||
content = view.editor.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (content === null) {
|
||||
// If the target file is not open, read it from the vault
|
||||
// Note: This is a fallback and might not be perfectly in sync with unsaved changes.
|
||||
this.app.vault.cachedRead(targetFile).then(fileContent => content = fileContent);
|
||||
if (content === null) return null;
|
||||
}
|
||||
|
||||
const subpath = parsedLinktext.subpath.substring(2); // remove #^
|
||||
const subpathMatch = subpath.match(/^(eq-[\w]+)(?:-(\d+))?$/);
|
||||
if (!subpathMatch) return null;
|
||||
|
|
@ -43,9 +28,9 @@ export class LatexLinkProvider extends Provider {
|
|||
const [, blockId, subIndexStr] = subpathMatch;
|
||||
const subIndex = subIndexStr ? parseInt(subIndexStr) : undefined;
|
||||
|
||||
const equations = processActiveNoteEquations(this.plugin, targetFile, content);
|
||||
const targetEquation = equations.get(blockId);
|
||||
|
||||
// Use the cache instead of parsing the file content manually
|
||||
const targetEquation = this.plugin.equationCache.get(targetFile.path, blockId);
|
||||
|
||||
if (targetEquation?.$printName) {
|
||||
let result: string;
|
||||
const settings = this.plugin.settings;
|
||||
|
|
@ -62,7 +47,7 @@ export class LatexLinkProvider extends Provider {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
95
src/main.ts
95
src/main.ts
|
|
@ -1,6 +1,8 @@
|
|||
import { MarkdownView, Plugin, TFile, parseLinktext } from 'obsidian';
|
||||
import { MarkdownView, Plugin, TFile, parseLinktext, Menu, TFolder } from 'obsidian';
|
||||
import type { Extension } from '@codemirror/state';
|
||||
import { around } from 'monkey-around';
|
||||
import * as fs from "fs/promises";
|
||||
import * as path from "path";
|
||||
|
||||
import { PluginSettings, DEFAULT_SETTINGS } from './features/settings/settings';
|
||||
import { MathSettingTab } from "./features/settings/tab";
|
||||
|
|
@ -20,6 +22,10 @@ import { EquationBlock } from 'types';
|
|||
// ADDED: Import our new internal patcher function
|
||||
import { patchSuggesterWithQuickPreview } from 'features/quick-preview/patcher';
|
||||
import { EquationCache } from './features/cache/equation-cache';
|
||||
import { ExportConfigModal } from "./features/export-pdf/modal";
|
||||
import { traverseFolder } from "./features/export-pdf/utils";
|
||||
|
||||
const isDev = process.env.NODE_ENV === "development";
|
||||
|
||||
export default class LatexReferencer extends Plugin {
|
||||
settings: PluginSettings;
|
||||
|
|
@ -65,6 +71,76 @@ export default class LatexReferencer extends Plugin {
|
|||
}
|
||||
});
|
||||
|
||||
this.addCommand({
|
||||
id: "export-current-file-to-pdf",
|
||||
name: "Export current file to PDF",
|
||||
checkCallback: (checking: boolean) => {
|
||||
const view = this.app.workspace.getActiveViewOfType(MarkdownView);
|
||||
const file = view?.file;
|
||||
if (!file) {
|
||||
return false;
|
||||
}
|
||||
if (checking) {
|
||||
return true;
|
||||
}
|
||||
new ExportConfigModal(this, file).open();
|
||||
|
||||
return true;
|
||||
},
|
||||
});
|
||||
|
||||
// Menu items for file export
|
||||
this.registerEvent(
|
||||
this.app.workspace.on("file-menu", (menu, file: TFile | TFolder) => {
|
||||
let title = file instanceof TFolder ? "Export folder to PDF" : "Better Export PDF";
|
||||
if (isDev) {
|
||||
title = `${title} (dev)`;
|
||||
}
|
||||
|
||||
menu.addItem((item) => {
|
||||
item
|
||||
.setTitle(title)
|
||||
.setIcon("download")
|
||||
.setSection("action")
|
||||
.onClick(async () => {
|
||||
new ExportConfigModal(this, file).open();
|
||||
});
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
this.registerEvent(
|
||||
this.app.workspace.on("file-menu", (menu, file: TFile | TFolder) => {
|
||||
if (file instanceof TFolder) {
|
||||
let title = "Export to PDF...";
|
||||
if (isDev) {
|
||||
title = `${title} (dev)`;
|
||||
}
|
||||
menu.addItem((item) => {
|
||||
item.setTitle(title).setIcon("lucide-folder-down").setSection("action");
|
||||
// @ts-ignore
|
||||
const subMenu: Menu = item.setSubmenu();
|
||||
subMenu.addItem((item) =>
|
||||
item
|
||||
.setTitle("Export each file to PDF")
|
||||
.setIcon("lucide-file-stack")
|
||||
.onClick(async () => {
|
||||
new ExportConfigModal(this, file, true).open();
|
||||
}),
|
||||
);
|
||||
subMenu.addItem((item) =>
|
||||
item
|
||||
.setTitle("Generate TOC.md file")
|
||||
.setIcon("lucide-file-text")
|
||||
.onClick(async () => {
|
||||
await this.generateToc(file);
|
||||
}),
|
||||
);
|
||||
});
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
// Editor Extensions
|
||||
this.editorExtensions = []
|
||||
this.registerEditorExtension(this.editorExtensions);
|
||||
|
|
@ -160,4 +236,21 @@ export default class LatexReferencer extends Plugin {
|
|||
|
||||
this.register(uninstaller);
|
||||
}
|
||||
|
||||
async generateToc(root: TFolder | TFile) {
|
||||
// @ts-ignore
|
||||
const basePath = this.app.vault.adapter.basePath;
|
||||
const toc = path.join(basePath, root.path, "_TOC_.md");
|
||||
const content = `---\ntoc: true\ntitle: ${root.name}\n---\n`;
|
||||
await fs.writeFile(toc, content);
|
||||
if (root instanceof TFolder) {
|
||||
const files = traverseFolder(root);
|
||||
for (const file of files) {
|
||||
if (file.name == "_TOC_.md") {
|
||||
continue;
|
||||
}
|
||||
await fs.appendFile(toc, `[[${file.path}]]\n`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue