rust runs in obsidian plugin, yay
This commit is contained in:
@@ -5,6 +5,11 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
clap = "4.5.59"
|
||||
deno_core = "0.385.0"
|
||||
mize = { path = "../mize/" }
|
||||
clap = { version = "4.5.59", optional = true }
|
||||
deno_core = { version = "0.385.0", optional = true }
|
||||
mize = { path = "../mize/", default-features = false }
|
||||
|
||||
[features]
|
||||
default = ["target-os"]
|
||||
target-os = [ "clap", "mize/target-os" ]
|
||||
target-wasm = [ "mize/target-wasm" ]
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#[cfg(feature = "target-os")]
|
||||
mod cli;
|
||||
#[cfg(feature = "target-os")]
|
||||
pub use cli::*;
|
||||
|
||||
//mod js;
|
||||
|
||||
@@ -17,12 +17,12 @@ crate-type = ["cdylib", "rlib"]
|
||||
[[bin]]
|
||||
name = "mize"
|
||||
path = "src/platform/os/main.rs"
|
||||
required-features = [ "os-target" ]
|
||||
required-features = [ "target-os" ]
|
||||
|
||||
[features]
|
||||
default = [ "os-target" ]
|
||||
os-target = [ "clap", "home", "nix", "sysinfo", "ciborium/default", "tracing-subscriber", "async", "tracing-subscriber/env-filter", "libloading", "ciborium-io", "tracing-core", "tar", "flate2", "http_req" ]
|
||||
wasm-target = [ "wasm-bindgen", "console_error_panic_hook", "wasm-bindgen-cli", "web-sys", "web-sys/Worker", "web-sys/Window", "web-sys/Request", "web-sys/RequestInit", "web-sys/RequestMode", "web-sys/Response", "web-sys/WorkerOptions", "web-sys/WorkerType", "serde-wasm-bindgen", "wasm-bindgen-futures", "wee_alloc"]
|
||||
default = [ "target-os" ]
|
||||
target-os= [ "clap", "home", "nix", "sysinfo", "ciborium/default", "tracing-subscriber", "async", "tracing-subscriber/env-filter", "libloading", "ciborium-io", "tracing-core", "tar", "flate2", "http_req" ]
|
||||
target-wasm = [ "wasm-bindgen", "console_error_panic_hook", "web-sys", "web-sys/Worker", "web-sys/Window", "web-sys/Request", "web-sys/RequestInit", "web-sys/RequestMode", "web-sys/Response", "web-sys/WorkerOptions", "web-sys/WorkerType", "serde-wasm-bindgen", "wasm-bindgen-futures", "wee_alloc"]
|
||||
async = ["tokio/net", "tokio", "tokio/rt-multi-thread", "tokio/io-util"]
|
||||
|
||||
|
||||
@@ -40,14 +40,14 @@ dyn-clone = "1.0.17"
|
||||
sha2 = "0.10.8"
|
||||
flume = "0.11.1"
|
||||
mize_macros = { path = "../macro_mize" }
|
||||
async-trait = "0.1.89"
|
||||
|
||||
# buildin modules
|
||||
# builtin modules
|
||||
#mize_module_blob = { path = "./modules/modules/Blob" }
|
||||
|
||||
# wasm dependencies
|
||||
wasm-bindgen = { version = "0.2.84", optional = true }
|
||||
console_error_panic_hook = { version = "0.1.7", optional = true }
|
||||
wasm-bindgen-cli = { version = "0.2.92", optional = true }
|
||||
web-sys = { version = "0.3.70", optional = true }
|
||||
serde-wasm-bindgen = { version = "0.6.5", optional = true }
|
||||
wasm-bindgen-futures = { version = "0.4.49", optional = true }
|
||||
@@ -75,7 +75,6 @@ http_req = { version = "0.12.0", default-features = false, features = [ "rust-tl
|
||||
axum = { version = "0.6.1", features = ["ws", "headers"], optional = true }
|
||||
axum-extra = { version = "0.4.2", features = ["spa"], optional = true }
|
||||
axum-macros = { version = "0.3.0", optional = true }
|
||||
async-trait = "0.1.89"
|
||||
#tokio-core = "0.1.18"
|
||||
#tokio-io = "0.1.13"
|
||||
|
||||
|
||||
@@ -18,5 +18,5 @@ nix build github:c2vi/mize#npmPackage
|
||||
|
||||
### without nix
|
||||
```bash
|
||||
wasm-pack build -- --features wasm-target
|
||||
wasm-pack build -- --features target-wasm
|
||||
```
|
||||
|
||||
@@ -55,7 +55,7 @@ let
|
||||
src = self;
|
||||
doCheck = false; # tests does not work in wasm
|
||||
CARGO_BUILD_TARGET = "wasm32-unknown-unknown";
|
||||
cargoExtraArgs = "--features wasm-target --no-default-features";
|
||||
cargoExtraArgs = "--features target-wasm --no-default-features";
|
||||
RUSTFLAGS="-C linker=wasm-ld";
|
||||
buildInputs = with pkgs; [ cargo-binutils lld ];
|
||||
});
|
||||
@@ -109,7 +109,7 @@ in {
|
||||
|
||||
one = craneLib.buildPackage {
|
||||
src = "${self}";
|
||||
#cargoExtraArgs = "--bin mize --features os-target";
|
||||
#cargoExtraArgs = "--bin mize --features target-os";
|
||||
cargoExtraArgs = "--bin mize";
|
||||
doCheck = false; # tests does not work in wasm
|
||||
CARGO_BUILD_TARGET = "x86_64-pc-windows-gnu";
|
||||
@@ -123,13 +123,13 @@ in {
|
||||
|
||||
default = osCrane.buildPackage {
|
||||
src = "${self}";
|
||||
cargoExtraArgs = "--bin mize --features os-target";
|
||||
cargoExtraArgs = "--bin mize --features target-os";
|
||||
};
|
||||
|
||||
wasm = wasmCrane.buildPackage {
|
||||
src = "${self}";
|
||||
CARGO_BUILD_TARGET = "wasm32-unknown-unknown";
|
||||
cargoExtraArgs = "--bin mize --features wasm-target";
|
||||
cargoExtraArgs = "--bin mize --features target-wasm ";
|
||||
doCheck = false;
|
||||
};
|
||||
inherit wasmArtifacts;
|
||||
@@ -154,7 +154,7 @@ in {
|
||||
mkdir -p $out/pkg
|
||||
|
||||
export HOME=$(mktemp -d fake-homeXXXX)
|
||||
wasm-pack build --out-dir $out/pkg --scope=c2vi -- --no-default-features --features wasm-target
|
||||
wasm-pack build --out-dir $out/pkg --scope=c2vi -- --no-default-features --features target-wasm
|
||||
'';
|
||||
|
||||
buildInputs = with pkgs; [ wasm-bindgen-cli binaryen wasm-pack wasmToolchain ];
|
||||
|
||||
@@ -269,7 +269,9 @@ rec {
|
||||
mkMizeRustShell = attrs: mkMizeModuleShell (attrs // {
|
||||
#_shell_type = "rust";
|
||||
nativeBuildInputs = attrs.nativeBuildInputs or [] ++ [
|
||||
pkgs.wasm-pack
|
||||
pkgs.pkg-config
|
||||
pkgs.wasm-bindgen-cli
|
||||
(fenix.packages."x86_64-linux".combine [
|
||||
fenix.packages."x86_64-linux".latest.toolchain
|
||||
fenix.packages."x86_64-linux".targets.wasm32-unknown-unknown.latest.toolchain
|
||||
|
||||
@@ -17,7 +17,7 @@ module = { mkMizeRustModule, mkMizeRustShell, hostSystem, pkgsCross, pkgs, lib,
|
||||
# linux stuff
|
||||
// (lib.attrsets.optionalAttrs (hostSystem.kernel.name == "linux") {
|
||||
strictDeps = true;
|
||||
cargoExtraArgs = "--bin mize --features os-target";
|
||||
cargoExtraArgs = "--bin mize --features target-os";
|
||||
mizeInstallPhase = ''
|
||||
mkdir -p $out
|
||||
cp $build_dir/target/${hostSystem.nameRust}/$debugOrRelease/mize $out/
|
||||
@@ -67,7 +67,7 @@ module = { mkMizeRustModule, mkMizeRustShell, hostSystem, pkgsCross, pkgs, lib,
|
||||
strictDeps = true;
|
||||
doCheck = false;
|
||||
|
||||
cargoExtraArgs = "--bin mize --features os-target";
|
||||
cargoExtraArgs = "--bin mize --features target-os";
|
||||
|
||||
CARGO_BUILD_TARGET = "${hostSystem.cpu.name}-pc-windows-gnu";
|
||||
|
||||
@@ -94,14 +94,14 @@ module = { mkMizeRustModule, mkMizeRustShell, hostSystem, pkgsCross, pkgs, lib,
|
||||
src = ./.;
|
||||
doCheck = false; # tests does not work in wasm
|
||||
CARGO_BUILD_TARGET = "wasm32-unknown-unknown";
|
||||
cargoExtraArgs = "--features wasm-target --no-default-features";
|
||||
cargoExtraArgs = "--features target-wasm --no-default-features";
|
||||
RUSTFLAGS="-C linker=wasm-ld";
|
||||
buildInputs = with pkgs; [ cargo-binutils lld ];
|
||||
});
|
||||
|
||||
mizeBuildPhase = ''
|
||||
cd $build_dir
|
||||
RUST_LOG=off wasm-pack build --target no-modules --dev --out-dir $out -- --features wasm-target --no-default-features
|
||||
RUST_LOG=off wasm-pack build --target no-modules --dev --out-dir $out -- --features target-wasm --no-default-features
|
||||
cat $build_dir/src/platform/wasm/init.js >> $out/mize.js
|
||||
'';
|
||||
mizeInstallPhase = "";
|
||||
@@ -113,7 +113,7 @@ module = { mkMizeRustModule, mkMizeRustShell, hostSystem, pkgsCross, pkgs, lib,
|
||||
buildPhaseCargoCommand = ''
|
||||
mkdir -p $out/pkg
|
||||
|
||||
HOME=$(mktemp -d fake-homeXXXX) wasm-pack build --target no-modules --out-dir $out/pkg --scope=c2vi -- --features wasm-target --no-default-features
|
||||
HOME=$(mktemp -d fake-homeXXXX) wasm-pack build --target no-modules --out-dir $out/pkg --scope=c2vi -- --features target-wasm --no-default-features
|
||||
'';
|
||||
|
||||
postInstall = ''
|
||||
|
||||
@@ -246,7 +246,7 @@ impl Mize {
|
||||
)),
|
||||
};
|
||||
|
||||
#[cfg(feature = "os-target")]
|
||||
#[cfg(feature = "target-os")]
|
||||
{
|
||||
let instance_clone = instance.clone();
|
||||
let op_rx_clone = op_rx.clone();
|
||||
@@ -259,7 +259,7 @@ impl Mize {
|
||||
}
|
||||
|
||||
// set up async update "threads" when using wasm
|
||||
#[cfg(feature = "wasm-target")]
|
||||
#[cfg(feature = "target-wasm ")]
|
||||
{
|
||||
let instance_clone = instance.clone();
|
||||
let op_rx_clone = op_rx.clone();
|
||||
@@ -275,14 +275,14 @@ impl Mize {
|
||||
//let msg_closure = move || msg_thread(op_rx, instance_clone);
|
||||
//instance.spawn("msg_thread", closure)?;
|
||||
|
||||
#[cfg(feature = "wasm-target")]
|
||||
#[cfg(feature = "target-wasm ")]
|
||||
console_log!("before loading build time config");
|
||||
|
||||
// load the config from build time
|
||||
let config = ItemData::from_toml(BUILD_TIME_CONFIG)?;
|
||||
instance.set_blocking("0", config);
|
||||
|
||||
#[cfg(feature = "wasm-target")]
|
||||
#[cfg(feature = "target-wasm ")]
|
||||
console_log!("after loading build time config");
|
||||
|
||||
return Ok(instance);
|
||||
@@ -343,7 +343,7 @@ impl Mize {
|
||||
match self.get("0/config/load_modules")?.value_string() {
|
||||
Ok(modules_to_load) => {
|
||||
for module in modules_to_load.split(" ") {
|
||||
#[cfg(feature = "wasm-target")]
|
||||
#[cfg(feature = "target-wasm ")]
|
||||
console_log!("loading module in Instance::init() ... {}", module);
|
||||
self.load_module(module)?;
|
||||
}
|
||||
@@ -695,10 +695,10 @@ impl Mize {
|
||||
|
||||
*next_thread_id += 1;
|
||||
|
||||
#[cfg(feature = "os-target")]
|
||||
#[cfg(feature = "target-os")]
|
||||
thread::spawn(move || to_spawn());
|
||||
|
||||
#[cfg(feature = "wasm-target")]
|
||||
#[cfg(feature = "target-wasm ")]
|
||||
{
|
||||
//console_log!("in instance::spawn with wasm target")
|
||||
}
|
||||
|
||||
@@ -22,10 +22,10 @@ pub trait Module {
|
||||
|
||||
// console_log macro
|
||||
// that can be copied into other files for debugging purposes
|
||||
#[cfg(feature = "wasm-target")]
|
||||
#[cfg(feature = "target-wasm ")]
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[cfg(feature = "wasm-target")]
|
||||
#[cfg(feature = "target-wasm ")]
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_namespace = console)]
|
||||
|
||||
@@ -60,7 +60,7 @@ pub mod platform {
|
||||
#[cfg(feature = "wasm-target")]
|
||||
pub mod wasm;
|
||||
|
||||
#[cfg(feature = "os-target")]
|
||||
#[cfg(feature = "target-os")]
|
||||
pub mod os;
|
||||
|
||||
pub mod any {
|
||||
@@ -68,35 +68,37 @@ pub mod platform {
|
||||
#[cfg(feature = "wasm-target")]
|
||||
pub use super::wasm::wasm_instance_init as instance_init;
|
||||
|
||||
#[cfg(feature = "os-target")]
|
||||
#[cfg(feature = "target-os")]
|
||||
pub use super::os::os_instance_init as instance_init;
|
||||
|
||||
#[cfg(not(any(feature = "os-target", feature = "wasm-target")))]
|
||||
#[cfg(not(any(feature = "target-os", feature = "target-wasm ")))]
|
||||
pub use super::super::instance_init;
|
||||
|
||||
//////////// load_module
|
||||
#[cfg(feature = "os-target")]
|
||||
#[cfg(feature = "target-os")]
|
||||
pub use super::os::load_module;
|
||||
|
||||
#[cfg(feature = "wasm-target")]
|
||||
pub use super::wasm::load_module;
|
||||
|
||||
#[cfg(not(any(feature = "os-target", feature = "wasm-target")))]
|
||||
#[cfg(not(any(feature = "target-os", feature = "target-wasm ")))]
|
||||
pub use super::super::load_module;
|
||||
|
||||
//////////// fetch_module
|
||||
#[cfg(feature = "os-target")]
|
||||
#[cfg(feature = "target-os")]
|
||||
pub use super::os::fetch_module;
|
||||
|
||||
#[cfg(feature = "wasm-target")]
|
||||
pub use super::super::fetch_module;
|
||||
|
||||
#[cfg(not(any(feature = "os-target", feature = "wasm-target")))]
|
||||
#[cfg(not(any(feature = "target-os", feature = "target-wasm ")))]
|
||||
pub use super::super::fetch_module;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn instance_init(instance: &mut core::instance::Mize) {}
|
||||
pub fn instance_init(instance: &mut core::instance::Mize) -> MizeResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn load_module(
|
||||
instance: &mut core::instance::Mize,
|
||||
|
||||
@@ -10,12 +10,12 @@ wasm-opt = false
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[features]
|
||||
default = [ "os-target" ]
|
||||
default = [ "target-os" ]
|
||||
qt = [ "slint", "cpp", "qt_core", "qt_gui", "qt_widgets", "comandr/qt" ]
|
||||
slint = [ "i-slint-backend-qt", "dep:slint", "slint-interpreter", "spin_on", "qt" ]
|
||||
os-target = [ "tao", "wry", "tracing-subscriber", "clap", "webkit2gtk", "mize/os-target", "glib" ]
|
||||
#os-target = [ "tao", "wry", "tracing-subscriber", "clap" ]
|
||||
wasm-target = [ "wasm-bindgen", "console_error_panic_hook", "wasm-bindgen-cli", "web-sys", "comandr/wasm-target", "mize/wasm-target" ]
|
||||
target-os= [ "tao", "wry", "tracing-subscriber", "clap", "webkit2gtk", "mize/target-os", "glib" ]
|
||||
#target-os= [ "tao", "wry", "tracing-subscriber", "clap" ]
|
||||
target-wasm = [ "wasm-bindgen", "console_error_panic_hook", "wasm-bindgen-cli", "web-sys", "comandr/target-wasm ", "mize/wasm-target" ]
|
||||
console_error_panic_hook = ["dep:console_error_panic_hook"]
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
|
||||
@@ -18,7 +18,7 @@ use wasm_bindgen::JsValue;
|
||||
#[cfg(feature = "wasm-target")]
|
||||
use web_sys::js_sys::Function;
|
||||
|
||||
//#[cfg(feature = "os-target")]
|
||||
//#[cfg(feature = "target-os")]
|
||||
//use crate::implementors::qt_widget::QtWidgetSlot;
|
||||
#[cfg(feature = "qt")]
|
||||
use qt_core::{qs, QString, QTimer, SlotNoArgs};
|
||||
@@ -142,7 +142,7 @@ impl Module for Mme {
|
||||
|
||||
println!("MmeModule init");
|
||||
|
||||
#[cfg(feature = "os-target")]
|
||||
#[cfg(feature = "target-os")]
|
||||
{
|
||||
//self.mize.spawn("mme-main", || self.create_x_window());
|
||||
let mut cloned_self = self.clone();
|
||||
@@ -212,7 +212,7 @@ impl Mme {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "os-target")]
|
||||
#[cfg(feature = "target-os")]
|
||||
pub fn create_x_window(&mut self) -> MizeResult<()> {
|
||||
use std::fs;
|
||||
|
||||
@@ -451,19 +451,19 @@ impl Mme {
|
||||
}
|
||||
|
||||
|
||||
#[cfg(feature = "os-target")]
|
||||
#[cfg(feature = "target-os")]
|
||||
use tao::{
|
||||
event::{Event, WindowEvent},
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
window::WindowBuilder,
|
||||
};
|
||||
#[cfg(feature = "os-target")]
|
||||
#[cfg(feature = "target-os")]
|
||||
use wry::{
|
||||
http::{self, header::CONTENT_TYPE, Request, Response},
|
||||
WebViewBuilder,
|
||||
};
|
||||
|
||||
#[cfg(feature = "os-target")]
|
||||
#[cfg(feature = "target-os")]
|
||||
fn get_wry_response(request: Request<Vec<u8>>, mut mme: Mme) -> Result<http::Response<Vec<u8>>, Box<dyn std::error::Error>> {
|
||||
use comandr::core::module;
|
||||
use mize::item::ItemData;
|
||||
|
||||
@@ -7,13 +7,13 @@ use ciborium::Value as CborValue;
|
||||
use flume::{ Receiver, Sender };
|
||||
use ciborium_io::Read;
|
||||
|
||||
#[cfg(feature = "os-target")]
|
||||
#[cfg(feature = "target-os")]
|
||||
use wry::http::Request;
|
||||
|
||||
#[cfg(feature = "os-target")]
|
||||
#[cfg(feature = "target-os")]
|
||||
use wry::WebView;
|
||||
|
||||
#[cfg(feature = "os-target")]
|
||||
#[cfg(feature = "target-os")]
|
||||
use tao::event_loop::EventLoopProxy;
|
||||
|
||||
#[cfg(feature = "wasm-target")]
|
||||
@@ -54,7 +54,7 @@ use mize::MizeError;
|
||||
|
||||
|
||||
|
||||
#[cfg(feature = "os-target")]
|
||||
#[cfg(feature = "target-os")]
|
||||
pub fn mme_setup_weview_con_host(mme: &mut Mme, rx: Receiver<MizeMessage>, event_loop_proxy: EventLoopProxy<MizeMessage>) -> MizeResult<()> {
|
||||
|
||||
let mize_clone = mme.mize.clone();
|
||||
|
||||
@@ -4,14 +4,24 @@ version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
mize = { path = "../mize" }
|
||||
marts = { path = "../marts/" }
|
||||
clap = "4.5.59"
|
||||
mize = { path = "../mize", default-features = false }
|
||||
marts = { path = "../marts/", default-features = false }
|
||||
clap = { version = "4.5.59", optional = true }
|
||||
js-sys = { version = "0.3.85", optional = true }
|
||||
wasm-bindgen = { version = "0.2.108", optional = true }
|
||||
|
||||
[[bin]]
|
||||
name = "ppc"
|
||||
path = "src/platform/os/main.rs"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
path = "src/lib.rs"
|
||||
|
||||
[features]
|
||||
default = ["target-os"]
|
||||
target-os = []
|
||||
target-os = [ "clap", "mize/target-os" ]
|
||||
target-obsidian = [ "js-sys", "wasm-bindgen", "mize/target-wasm", "marts/target-wasm" ]
|
||||
|
||||
[package.metadata.wasm-pack.profile.release]
|
||||
wasm-opt = false
|
||||
|
||||
4
crates/ppc/src/lib.rs
Normal file
4
crates/ppc/src/lib.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
mod platform {
|
||||
#[cfg(feature = "target-obsidian")]
|
||||
mod obsidian;
|
||||
}
|
||||
54
crates/ppc/src/platform/obsidian/esbuild.config.js
Normal file
54
crates/ppc/src/platform/obsidian/esbuild.config.js
Normal file
@@ -0,0 +1,54 @@
|
||||
import esbuild from "esbuild";
|
||||
import process from "process";
|
||||
import builtins from "builtin-modules";
|
||||
|
||||
const banner =
|
||||
`/*
|
||||
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||||
*/
|
||||
`;
|
||||
|
||||
const prod = (process.argv[2] === "production");
|
||||
|
||||
const context = await esbuild.context({
|
||||
banner: {
|
||||
js: banner,
|
||||
},
|
||||
entryPoints: ["plugin.ts"],
|
||||
bundle: true,
|
||||
external: [
|
||||
"obsidian",
|
||||
"electron",
|
||||
"@codemirror/autocomplete",
|
||||
"@codemirror/collab",
|
||||
"@codemirror/commands",
|
||||
"@codemirror/language",
|
||||
"@codemirror/lint",
|
||||
"@codemirror/search",
|
||||
"@codemirror/state",
|
||||
"@codemirror/view",
|
||||
"@lezer/common",
|
||||
"@lezer/highlight",
|
||||
"@lezer/lr",
|
||||
...builtins],
|
||||
format: "cjs",
|
||||
target: "es2020",
|
||||
logLevel: "info",
|
||||
sourcemap: prod ? false : "inline",
|
||||
treeShaking: true,
|
||||
outfile: "dist/main.js",
|
||||
loader: {
|
||||
".wasm": "binary",
|
||||
".workerjs": "text"
|
||||
},
|
||||
define: {
|
||||
"import.meta.url": '"obsidian-plugin"'
|
||||
},
|
||||
});
|
||||
|
||||
if (prod) {
|
||||
await context.rebuild();
|
||||
process.exit(0);
|
||||
} else {
|
||||
await context.watch();
|
||||
}
|
||||
49
crates/ppc/src/platform/obsidian/esbuild.config.mjs
Normal file
49
crates/ppc/src/platform/obsidian/esbuild.config.mjs
Normal file
@@ -0,0 +1,49 @@
|
||||
import esbuild from "esbuild";
|
||||
import process from "process";
|
||||
import builtins from "builtin-modules";
|
||||
|
||||
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
|
||||
*/
|
||||
`;
|
||||
|
||||
const prod = (process.argv[2] === "production");
|
||||
|
||||
const context = await esbuild.context({
|
||||
banner: {
|
||||
js: banner,
|
||||
},
|
||||
entryPoints: ["./plugin.ts"],
|
||||
bundle: true,
|
||||
external: [
|
||||
"obsidian",
|
||||
"electron",
|
||||
"@codemirror/autocomplete",
|
||||
"@codemirror/collab",
|
||||
"@codemirror/commands",
|
||||
"@codemirror/language",
|
||||
"@codemirror/lint",
|
||||
"@codemirror/search",
|
||||
"@codemirror/state",
|
||||
"@codemirror/view",
|
||||
"@lezer/common",
|
||||
"@lezer/highlight",
|
||||
"@lezer/lr",
|
||||
...builtins],
|
||||
format: "cjs",
|
||||
target: "es2018",
|
||||
logLevel: "info",
|
||||
sourcemap: prod ? false : "inline",
|
||||
treeShaking: true,
|
||||
outfile: "dist/main.js",
|
||||
minify: false,
|
||||
});
|
||||
|
||||
if (prod) {
|
||||
await context.rebuild();
|
||||
process.exit(0);
|
||||
} else {
|
||||
await context.watch();
|
||||
}
|
||||
10
crates/ppc/src/platform/obsidian/manifest.json
Normal file
10
crates/ppc/src/platform/obsidian/manifest.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"id": "ppc",
|
||||
"name": "PPC Obsidian Plugin",
|
||||
"version": "0.1.0",
|
||||
"minAppVersion": "1.5.0",
|
||||
"main": "main.js",
|
||||
"author": "ppc",
|
||||
"isDesktopOnly": true,
|
||||
"description": "Turns Obsidian into a full on PPC client"
|
||||
}
|
||||
23
crates/ppc/src/platform/obsidian/mod.rs
Normal file
23
crates/ppc/src/platform/obsidian/mod.rs
Normal file
@@ -0,0 +1,23 @@
|
||||
use mize::Mize;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
// console_log macro
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_namespace = console)]
|
||||
fn log(s: &str);
|
||||
}
|
||||
|
||||
macro_rules! console_log {
|
||||
// Note that this is using the `log` function imported above during
|
||||
// `bare_bones`
|
||||
($($t:tt)*) => ({ log(&format_args!($($t)*).to_string())})
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn obsidian_mize_entrypoint() {
|
||||
console_log!("hiiiiiiiiiiiii from rust");
|
||||
let mize = Mize::new();
|
||||
console_log!("Obsidian Mize initialized");
|
||||
}
|
||||
46
crates/ppc/src/platform/obsidian/package.json
Normal file
46
crates/ppc/src/platform/obsidian/package.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "ppc-obsidian-plugin",
|
||||
"version": "0.1.0",
|
||||
"description": "Turnes obsidian into an PPC client",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"build:rust": "wasm-pack -vvvvv build -d src/platform/obsidian/rust_dist --target web --no-default-features --features target-obsidian",
|
||||
"build": "npm run build:rust && mkdir -p dist && touch dist/.hotreload && cp manifest.json dist && node esbuild.config.js production",
|
||||
"dev": ""
|
||||
},
|
||||
"keywords": [
|
||||
"obsidian",
|
||||
"plugin"
|
||||
],
|
||||
"author": "c2vi",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@flowershow/remark-wiki-link": "^2.0.4",
|
||||
"@instantdb/admin": "^0.21.3",
|
||||
"@instantdb/react": "^0.20.28",
|
||||
"@react-oauth/google": "^0.12.2",
|
||||
"esbuild": "^0.27.3",
|
||||
"mdast": "^3.0.0",
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0",
|
||||
"remark-frontmatter": "^5.0.0",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"remark-parse": "^11.0.0",
|
||||
"remark-stringify": "^11.0.0",
|
||||
"unified": "^11.0.5",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "^4",
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"@wasm-tool/rollup-plugin-rust": "^3.1.4",
|
||||
"binaryen": "^125.0.0",
|
||||
"builtin-modules": "3.3.0",
|
||||
"obsidian": "latest",
|
||||
"tailwindcss": "^4",
|
||||
"tslib": "^2.6.2",
|
||||
"typescript": "^5.5.4"
|
||||
}
|
||||
}
|
||||
598
crates/ppc/src/platform/obsidian/plugin.ts
Normal file
598
crates/ppc/src/platform/obsidian/plugin.ts
Normal file
@@ -0,0 +1,598 @@
|
||||
import { Plugin, TFile, Vault, MetadataCache } from "obsidian";
|
||||
import { id, i, init, InstaQLEntity } from "@instantdb/react";
|
||||
import remarkParse from "remark-parse";
|
||||
import remarkStringify from "remark-stringify";
|
||||
import { unified } from "unified";
|
||||
import { visit } from "unist-util-visit";
|
||||
import { Root, Content, Heading, List, ListItem, Text } from "mdast";
|
||||
import remarkFrontmatter from "remark-frontmatter";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import wikiLinkPlugin from "@flowershow/remark-wiki-link";
|
||||
import wasmBinary from "./rust_dist/ppc_bg.wasm";
|
||||
import * as wasmNamespace from "./rust_dist/ppc";
|
||||
|
||||
const OTASK_PROP_NAMES = ["short", "outcome", "priority"];
|
||||
const ACTION_PROP_NAMES = [];
|
||||
|
||||
const REMARK = unified()
|
||||
.use(remarkParse)
|
||||
.use(remarkFrontmatter)
|
||||
.use(remarkGfm)
|
||||
.use(remarkStringify, { bullet: "-" });
|
||||
|
||||
export default class PPCObsidianPlugin extends Plugin {
|
||||
async onload() {
|
||||
// init mize from wasm
|
||||
const wasmModule = await import("./rust_dist/ppc.js");
|
||||
await wasmModule.default({ module_or_path: wasmBinary });
|
||||
console.log("hoooo wasmModule:", wasmModule);
|
||||
wasmModule.initSync();
|
||||
|
||||
//console.log("");
|
||||
//const buffer = Uint8Array.from(atob(rustPlugin), (c) => c.charCodeAt(0));
|
||||
wasmModule.obsidian_mize_entrypoint();
|
||||
|
||||
// Listen for file modifications in the vault
|
||||
//this.registerEvent(
|
||||
//this.app.vault.on("modify", (file: TFile) => {
|
||||
//this.handleFileUpdate(file);
|
||||
//})
|
||||
//);
|
||||
|
||||
//this.registerView(
|
||||
//"system-c2-app",
|
||||
//(leaf) => new AppReactView(leaf, this)
|
||||
//);
|
||||
|
||||
this.addCommand({
|
||||
id: "app",
|
||||
name: "Open SystemC2 App page",
|
||||
callback: async () => {
|
||||
const leaf = this.app.workspace.getLeaf(true);
|
||||
await leaf.setViewState({
|
||||
type: "system-c2-app",
|
||||
active: true,
|
||||
});
|
||||
this.app.workspace.revealLeaf(leaf);
|
||||
},
|
||||
});
|
||||
|
||||
this.addCommand({
|
||||
id: "full-parse",
|
||||
name: "Parse all otask files into the db",
|
||||
callback: async () => {
|
||||
await full_parse();
|
||||
},
|
||||
});
|
||||
|
||||
//full_parse(this.db)
|
||||
}
|
||||
|
||||
async handleFileUpdate(file: TFile) {
|
||||
if (!(file instanceof TFile) || file.extension !== "md") {
|
||||
return; // only care about markdown files
|
||||
}
|
||||
|
||||
const metadata = this.app.metadataCache.getFileCache(file);
|
||||
|
||||
// Example: check if the file has a specific tag
|
||||
if (metadata?.frontmatter?.tags?.includes("t/otask")) {
|
||||
this.parseOtask(file);
|
||||
}
|
||||
}
|
||||
|
||||
async parseOtask(file: TFile) {
|
||||
if (!this.isLoggedIn()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isRrootOtask = file.basename === "my-projects";
|
||||
|
||||
if (isRrootOtask) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
async isLoggedIn() {
|
||||
const user = this.db.getAuth();
|
||||
user;
|
||||
}
|
||||
|
||||
onunload() {
|
||||
this.app.workspace.detachLeavesOfType("system-c2-app");
|
||||
}
|
||||
}
|
||||
|
||||
let OTASK_PARSE_QUEUE = [];
|
||||
|
||||
let OTASK_LIST = [];
|
||||
|
||||
let DBG = false;
|
||||
|
||||
function dbg() {
|
||||
if (DBG) {
|
||||
console.log(arguments);
|
||||
}
|
||||
}
|
||||
|
||||
function queue_otasks_from_list_item(listItem, otask_path, priority = 0) {
|
||||
OTASK_PARSE_QUEUE.push({
|
||||
listItem,
|
||||
otask_path,
|
||||
priority,
|
||||
});
|
||||
}
|
||||
|
||||
function queue_otasks_from_file(file, otask_path, priority = 0) {
|
||||
OTASK_PARSE_QUEUE.push({
|
||||
file,
|
||||
otask_path,
|
||||
priority,
|
||||
});
|
||||
}
|
||||
|
||||
// parsing helper functions
|
||||
|
||||
async function full_parse() {
|
||||
console.log("full parse.......................... yay");
|
||||
let otasks = [];
|
||||
OTASK_PARSE_QUEUE = [];
|
||||
OTASK_LIST = [];
|
||||
|
||||
const root_file = app.vault.getAbstractFileByPath("task/my-projects.md");
|
||||
|
||||
const content = await app.vault.read(root_file);
|
||||
const list = await getListUnderHeading(content, "root");
|
||||
|
||||
for (const entry of list) {
|
||||
queue_otasks_from_list_item(entry, []);
|
||||
}
|
||||
|
||||
// go through the queue of otaskParseTasks
|
||||
// using a queue instead of recursive calls, to make it more debuggable...
|
||||
do {
|
||||
const task = OTASK_PARSE_QUEUE.shift();
|
||||
dbg("task", task);
|
||||
if (task.file) {
|
||||
const otask = await otasks_from_file(
|
||||
task.file,
|
||||
task.otask_path,
|
||||
task.priority,
|
||||
);
|
||||
dbg("otask", otask);
|
||||
if (otask) {
|
||||
OTASK_LIST.push(otask);
|
||||
}
|
||||
} else {
|
||||
const otask = await otasks_from_list_item(
|
||||
task.listItem,
|
||||
task.otask_path,
|
||||
task.priority,
|
||||
);
|
||||
dbg("otask", otask);
|
||||
if (otask) {
|
||||
OTASK_LIST.push(otask);
|
||||
}
|
||||
}
|
||||
} while (OTASK_PARSE_QUEUE.length > 0);
|
||||
|
||||
console.log("otasks::", OTASK_LIST);
|
||||
|
||||
render_sub0_file(OTASK_LIST);
|
||||
}
|
||||
|
||||
async function render_sub0_file(otasks) {
|
||||
const sub0_file = app.vault.getAbstractFileByPath("private/sub0-tasks.md");
|
||||
if (!(sub0_file instanceof TFile)) {
|
||||
console.error(
|
||||
"SystemC2: sub0_file not found:",
|
||||
"private/sub0-tasks.md",
|
||||
sub0_file,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
//render sub0
|
||||
const sub0_otasks = otasks.filter(
|
||||
(otask) => otask.priority == 0 && !otask.is_file,
|
||||
);
|
||||
console.log("sub0 otasks...", sub0_otasks);
|
||||
|
||||
let rendered_otasks_string = "";
|
||||
|
||||
for (const otask of sub0_otasks) {
|
||||
const path_part = otask.path.length > 0 ? otask.path.join(": ") + ": " : "";
|
||||
|
||||
let content_part = otask.content ? otask.content + "\n" : "";
|
||||
content_part = content_part
|
||||
.split("\n")
|
||||
.map((line) => "\t" + line)
|
||||
.join("\n"); // add a \t in front of every otask.content line
|
||||
|
||||
rendered_otasks_string += `- ${path_part}${otask.longName}\n${content_part}\n`;
|
||||
}
|
||||
//console.log("newContent...", rendered_otasks_string)
|
||||
|
||||
await replaceHeading(sub0_file, "sub0", rendered_otasks_string);
|
||||
|
||||
//render sub-1
|
||||
}
|
||||
|
||||
async function replaceHeading(
|
||||
file: TFile,
|
||||
heading: string,
|
||||
newContent: string,
|
||||
) {
|
||||
const data = await this.app.vault.read(file);
|
||||
|
||||
// Parse the Markdown into an AST
|
||||
const tree = REMARK.parse(data) as Root;
|
||||
|
||||
// Split new content into AST nodes
|
||||
const newContentAst = REMARK.parse(newContent) as Root;
|
||||
|
||||
const children = tree.children;
|
||||
const newChildren: Content[] = [];
|
||||
let insideTarget = false;
|
||||
let targetLevel = 0;
|
||||
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const node = children[i];
|
||||
|
||||
if (node.type === "heading") {
|
||||
const headingNode = node as Heading;
|
||||
const text = headingNode.children
|
||||
.filter((c) => c.type === "text")
|
||||
.map((c: any) => c.value)
|
||||
.join("");
|
||||
|
||||
// If we encounter our target heading
|
||||
if (text.trim() === heading) {
|
||||
insideTarget = true;
|
||||
targetLevel = headingNode.depth;
|
||||
newChildren.push(node); // Keep the heading itself
|
||||
// Insert new content right after
|
||||
newChildren.push(...newContentAst.children);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we’re currently inside target section and see a heading of same or higher level
|
||||
if (insideTarget && headingNode.depth <= targetLevel) {
|
||||
insideTarget = false;
|
||||
}
|
||||
}
|
||||
|
||||
// If we’re not inside the target section, keep the node
|
||||
if (!insideTarget) {
|
||||
newChildren.push(node);
|
||||
}
|
||||
}
|
||||
|
||||
const newTree: Root = { ...tree, children: newChildren };
|
||||
|
||||
// Convert AST back to Markdown
|
||||
const newMarkdown = await REMARK.stringify(newTree);
|
||||
|
||||
await this.app.vault.modify(file, newMarkdown);
|
||||
}
|
||||
|
||||
async function otasks_from_list_item(listItem, otask_path, priority = 0) {
|
||||
// the main otask this listItem is about
|
||||
let otask = {
|
||||
description: [],
|
||||
actions: [],
|
||||
path: [],
|
||||
priority,
|
||||
};
|
||||
dbg("SystemC2: otasks_from_list_item", listItem, otask_path);
|
||||
|
||||
if (!listItem.children[0].type === "paragraph") {
|
||||
dbg(
|
||||
"listItem[0] of a otask item is not a paragraph... the otask:",
|
||||
listItem,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
let longName = nodeToString(listItem.children[0]);
|
||||
|
||||
dbg("longName:", longName);
|
||||
|
||||
// check for [[anotherotask]], call otasks_from_file, return those
|
||||
const match = longName.match(/\[\[([^\]]+)\]\]/);
|
||||
if (match) {
|
||||
const file = app.metadataCache.getFirstLinkpathDest(match[1], "");
|
||||
if (file) {
|
||||
const metadata = app.metadataCache.getFileCache(file);
|
||||
|
||||
if (metadata?.frontmatter?.tags?.includes("t/otask")) {
|
||||
queue_otasks_from_file(file, otask_path);
|
||||
return null;
|
||||
} else {
|
||||
dbg(
|
||||
"SystemC2: listItem with Link to '",
|
||||
match[1],
|
||||
"', which is not an otask",
|
||||
longName,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//check for [x] and remove from name
|
||||
if (longName.startsWith("[ ") || longName.startsWith("[x")) {
|
||||
longName = longName.slice(4);
|
||||
}
|
||||
|
||||
//check for "ot:" and remove from name
|
||||
if (longName.startsWith("ot:")) {
|
||||
longName = longName.slice(4);
|
||||
}
|
||||
|
||||
otask.longName = longName;
|
||||
otask.short = longName;
|
||||
otask.path = otask_path;
|
||||
let new_otask_path = [...otask_path, otask.short];
|
||||
|
||||
// go through sub list items
|
||||
// - if it's a prop for the otask... handle that
|
||||
// - if it's an "ac:" handle that
|
||||
// - if it's "ot: " handle as another otask -> recursive call
|
||||
// - if it's "[ ]" handle as another otask -> recursive call
|
||||
// - if it's a link to a otask file... handle as another otask -> call otasks_from_file()
|
||||
// - else add it as description item list to otask
|
||||
if (!listItem.children || listItem.children.length < 2) {
|
||||
return otask;
|
||||
}
|
||||
|
||||
// add content as text to otask
|
||||
if (otask.longName == "hosting updates") {
|
||||
console.log("listItem... ", listItem.children[1]);
|
||||
let hii = REMARK.stringify(listItem.children[1]);
|
||||
console.log("text...", hii);
|
||||
}
|
||||
let content_text = REMARK.stringify(listItem.children[1]);
|
||||
otask.content = content_text;
|
||||
|
||||
for (const subListItem of listItem.children[1].children) {
|
||||
let text = nodeToString(subListItem.children[0]);
|
||||
|
||||
// check prop
|
||||
if (check_otask_prop_from_list_item(subListItem, otask)) {
|
||||
new_otask_path = [...otask_path, otask.short]; // have to redo it here, in case short changed from aprop
|
||||
continue; // don't do any other processing on this sub-listItem
|
||||
}
|
||||
|
||||
// remove "[ ]"
|
||||
if (text.startsWith("[ ") || text.startsWith("[x")) {
|
||||
text = text.slice(4);
|
||||
}
|
||||
|
||||
// check ac
|
||||
if (text.startsWith("ac:")) {
|
||||
otask.actions = [
|
||||
...otask.actions,
|
||||
action_from_list_item(subListItem, new_otask_path, otask.priority),
|
||||
];
|
||||
|
||||
continue; // don't do any other processing on this sub-listItem
|
||||
}
|
||||
|
||||
// check ot
|
||||
if (text.startsWith("ot:")) {
|
||||
queue_otasks_from_list_item(subListItem, new_otask_path, otask.priority);
|
||||
|
||||
continue; // don't do any other processing on this sub-listItem
|
||||
}
|
||||
|
||||
// check [ ]
|
||||
if (text.startsWith("[ ] ") || text.startsWith("[x] ")) {
|
||||
queue_otasks_from_list_item(subListItem, new_otask_path, otask.priority);
|
||||
|
||||
continue; // don't do any other processing on this sub-listItem
|
||||
}
|
||||
|
||||
// check link to otask file
|
||||
const match = text.match(/\[\[([^\]]+)\]\]/);
|
||||
if (match) {
|
||||
const file = app.metadataCache.getFirstLinkpathDest(match[1], "");
|
||||
if (file) {
|
||||
const metadata = app.metadataCache.getFileCache(file);
|
||||
|
||||
if (metadata?.frontmatter?.tags?.includes("t/otask")) {
|
||||
queue_otasks_from_file(file, new_otask_path, otask.priority);
|
||||
continue;
|
||||
} else {
|
||||
dbg(
|
||||
"SystemC2: listItem with Link to '",
|
||||
match[1],
|
||||
"', which is not an otask",
|
||||
longName,
|
||||
);
|
||||
}
|
||||
|
||||
continue; // don't do any other processing on this sub-listItem
|
||||
}
|
||||
}
|
||||
|
||||
// add as description
|
||||
const desc = REMARK.stringify(subListItem);
|
||||
otask.description.push(desc);
|
||||
}
|
||||
|
||||
return otask;
|
||||
}
|
||||
|
||||
async function otasks_from_file(file: TFile, otask_path, priority = 0) {
|
||||
dbg("SystemC2: otasks_from_file", file, otask_path);
|
||||
|
||||
// the main otask this file is about
|
||||
let otask = {
|
||||
description: [],
|
||||
actions: [],
|
||||
path: [],
|
||||
priority,
|
||||
is_file: true,
|
||||
};
|
||||
|
||||
otask.longName = file.basename;
|
||||
otask.short = otask.longName;
|
||||
otask.path = otask_path;
|
||||
let new_otask_path = [...otask_path, otask.short];
|
||||
|
||||
const content = await app.vault.read(file);
|
||||
|
||||
// parse listItems at the top... for props
|
||||
const topListItems = getListItemsBeforeFirstHeading(content);
|
||||
for (const topListItem of topListItems) {
|
||||
const text = nodeToString(topListItem);
|
||||
|
||||
// check for prop
|
||||
if (check_otask_prop_from_list_item(topListItem, otask)) {
|
||||
new_otask_path = [...otask_path, otask.short];
|
||||
continue; // don't do any other processing on this sub-listItem
|
||||
}
|
||||
}
|
||||
|
||||
// parse all the sub sections
|
||||
const SUB_COUNT = 10;
|
||||
for (let sub_number = 0; sub_number < SUB_COUNT; sub_number++) {
|
||||
let listItems = await getListUnderHeading(content, "sub" + sub_number);
|
||||
|
||||
// "sub" without a number should have priority 5
|
||||
if (sub_number == 5) {
|
||||
listItems = listItems.concat(await getListUnderHeading(content, "sub"));
|
||||
}
|
||||
|
||||
//dbg(`sub section ${sub_number} has items:`, listItems)
|
||||
|
||||
for (const listItem of listItems) {
|
||||
// check if listItem is an action...
|
||||
let text = nodeToString(listItem.children[0]);
|
||||
if (
|
||||
text.startsWith("ac:") ||
|
||||
text.startsWith("[ ] ac:") ||
|
||||
text.startsWith("[x] ac:")
|
||||
) {
|
||||
const action = action_from_list_item(listItem, otask_path);
|
||||
otask.actions.push(action);
|
||||
}
|
||||
|
||||
queue_otasks_from_list_item(
|
||||
listItem,
|
||||
new_otask_path,
|
||||
otask.priority + sub_number,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return otask;
|
||||
}
|
||||
|
||||
function action_from_list_item(listItem, otask_path) {
|
||||
dbg("SystemC2: action_from_list_item", listItem, otask_path);
|
||||
let action = {};
|
||||
let text = nodeToString(listItem.children[0]).slice(4);
|
||||
|
||||
if (text.startsWith("[")) {
|
||||
text = text.slice(4);
|
||||
}
|
||||
|
||||
action.name = text;
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
function check_otask_prop_from_list_item(listItem, otask) {
|
||||
let text = nodeToString(listItem.children[0]);
|
||||
|
||||
for (const prop_name of OTASK_PROP_NAMES) {
|
||||
if (text.startsWith(prop_name + ":")) {
|
||||
const value = text.slice(prop_name.length + 2);
|
||||
|
||||
if (prop_name == "priority") {
|
||||
// parse priority as int
|
||||
otask[prop_name] = parseInt(value);
|
||||
} else if (prop_name == "outcome") {
|
||||
// add sub items to it
|
||||
let fullText = REMARK.stringify(listItem).slice(prop_name.length + 4);
|
||||
otask[prop_name] = fullText;
|
||||
} else {
|
||||
otask[prop_name] = value;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extract plain text from a node
|
||||
function nodeToString(node: any): string {
|
||||
let result = "";
|
||||
visit(node, "text", (textNode: Text) => {
|
||||
result += textNode.value;
|
||||
});
|
||||
return result.trim();
|
||||
}
|
||||
|
||||
async function getListUnderHeading(
|
||||
markdown: string,
|
||||
headingText: string,
|
||||
): string[] {
|
||||
const tree = REMARK.parse(markdown);
|
||||
//dbg("tree", tree)
|
||||
|
||||
let capture = false;
|
||||
let items: string[] = [];
|
||||
|
||||
for (let i = 0; i < tree.children.length; i++) {
|
||||
const node: Content = tree.children[i];
|
||||
|
||||
// Detect the target heading
|
||||
if (
|
||||
node.type === "heading" &&
|
||||
nodeToString(node).toLowerCase() === headingText.toLowerCase()
|
||||
) {
|
||||
capture = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Stop if another heading of the same or higher level comes
|
||||
if (capture && node.type === "heading") {
|
||||
break;
|
||||
}
|
||||
|
||||
// Collect list items if capturing
|
||||
if (capture && node.type === "list") {
|
||||
for (const li of (node as List).children) {
|
||||
if (li.type === "listItem") {
|
||||
items.push(li);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
function getListItemsBeforeFirstHeading(markdown: string) {
|
||||
const tree = REMARK.parse(markdown);
|
||||
|
||||
let items = [];
|
||||
|
||||
for (const node of tree.children) {
|
||||
if (node.type === "heading") {
|
||||
// stop at first heading
|
||||
break;
|
||||
}
|
||||
if (node.type === "list") {
|
||||
for (const li of (node as List).children) {
|
||||
if (li.type === "listItem") {
|
||||
items.push(li);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
2128
crates/ppc/src/platform/obsidian/pnpm-lock.yaml
generated
Normal file
2128
crates/ppc/src/platform/obsidian/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
36
crates/ppc/src/platform/obsidian/rollup.config.js
Normal file
36
crates/ppc/src/platform/obsidian/rollup.config.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import { nodeResolve } from "@rollup/plugin-node-resolve";
|
||||
import commonjs from "@rollup/plugin-commonjs";
|
||||
import { base64 } from "rollup-plugin-base64";
|
||||
import typescript from "@rollup/plugin-typescript";
|
||||
import rust from "@wasm-tool/rollup-plugin-rust";
|
||||
|
||||
const banner = `/*
|
||||
THIS IS A GENERATED/BUNDLED FILE BY ROLLUP
|
||||
if you want to view the source visit the plugins github repository
|
||||
*/
|
||||
`;
|
||||
|
||||
export default {
|
||||
input: "plugin.ts",
|
||||
output: {
|
||||
file: "dist/main.js",
|
||||
sourcemap: "inline",
|
||||
format: "cjs",
|
||||
exports: "default",
|
||||
banner,
|
||||
},
|
||||
external: ["obsidian"],
|
||||
plugins: [
|
||||
//nodeResolve({ browser: true }),
|
||||
//commonjs(),
|
||||
//base64({ include: "**/*.wasm" }),
|
||||
typescript(),
|
||||
rust({
|
||||
inlineWasm: true,
|
||||
verbose: true,
|
||||
extraArgs: {
|
||||
cargo: ["--no-default-features", "--features", "target-obsidian"],
|
||||
},
|
||||
}),
|
||||
],
|
||||
};
|
||||
1
crates/ppc/src/platform/obsidian/run
Normal file
1
crates/ppc/src/platform/obsidian/run
Normal file
@@ -0,0 +1 @@
|
||||
cargo rustc --lib --target wasm32-unknown-unknown --crate-type cdylib --release --config 'profile.release.panic="abort"' --config profile.release.lto=true --config profile.release.codegen-units=1 --config profile.release.strip=true -Z panic-immediate-abort -Z build-std=panic_abort,core,std,alloc,proc_macro -Z build-std-features=optimize_for_size --config build.rustflags=["-Z","location-detail=none","-Z","fmt-debug=none"] --no-default-features --features target-obsidian
|
||||
@@ -23,7 +23,7 @@ serde_json = "1.0.117"
|
||||
tar = "0.4.44"
|
||||
umask = "2.1.0"
|
||||
#mize = { git = "https://github.com/c2vi/mize", default-features = false }
|
||||
mize = { path = "../mize", default-features = false, features = ["os-target"] }
|
||||
mize = { path = "../mize", default-features = false, features = ["target-os"] }
|
||||
|
||||
# snix testing
|
||||
#snix-cli = { git = "https://git.snix.dev/snix/snix" }
|
||||
|
||||
Reference in New Issue
Block a user