Switch to SvelteKit (#3077)

* Update to latest Node LTS

* Add sveltekit

* Split tslib into separate @generated and @tslib components

SvelteKit's path aliases don't support multiple locations, so our old
approach of using @tslib to refer to both ts/lib and out/ts/lib will no
longer work. Instead, all generated sources and their includes are
placed in a separate out/ts/generated folder, and imported via @generated
instead. This also allows us to generate .ts files, instead of needing
to output separate .d.ts and .js files.

* Switch package.json to module type

* Avoid usage of baseUrl

Incompatible with SvelteKit

* Move sass into ts; use relative links

SvelteKit's default sass support doesn't allow overriding loadPaths

* jest->vitest, graphs example working with yarn dev

* most pages working in dev mode

* Some fixes after rebasing

* Fix/silence some svelte-check errors

* Get image-occlusion working with Fabric types

* Post-rebase lock changes

* Editor is now checked

* SvelteKit build integrated into ninja

* Use the new SvelteKit entrypoint for pages like congrats/deck options/etc

* Run eslint once for ts/**; fix some tests

* Fix a bunch of issues introduced when rebasing over latest main

* Run eslint fix

* Fix remaining eslint+pylint issues; tests now all pass

* Fix some issues with a clean build

* Latest bufbuild no longer requires @__PURE__ hack

* Add a few missed dependencies

* Add yarn.bat to fix Windows build

* Fix pages failing to show when ANKI_API_PORT not defined

* Fix svelte-check and vitest on Windows

* Set node path in ./yarn

* Move svelte-kit output to ts/.svelte-kit

Sadly, I couldn't figure out a way to store it in out/ if out/ is
a symlink, as it breaks module resolution when SvelteKit is run.

* Allow HMR inside Anki

* Skip SvelteKit build when HMR is defined

* Fix some post-rebase issues

I should have done a normal merge instead.
This commit is contained in:
Damien Elmes 2024-03-31 09:16:31 +01:00 committed by GitHub
parent 429bc9e14c
commit 9f55cf26fc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
527 changed files with 2933 additions and 3676 deletions

View File

@ -1,7 +1,6 @@
[env] [env]
STRINGS_PY = { value = "out/pylib/anki/_fluent.py", relative = true } STRINGS_PY = { value = "out/pylib/anki/_fluent.py", relative = true }
STRINGS_JS = { value = "out/ts/lib/ftl.js", relative = true } STRINGS_TS = { value = "out/ts/lib/generated/ftl.ts", relative = true }
STRINGS_DTS = { value = "out/ts/lib/ftl.d.ts", relative = true }
DESCRIPTORS_BIN = { value = "out/rslib/proto/descriptors.bin", relative = true } DESCRIPTORS_BIN = { value = "out/rslib/proto/descriptors.bin", relative = true }
# build script will append .exe if necessary # build script will append .exe if necessary
PROTOC = { value = "out/extracted/protoc/bin/protoc", relative = true } PROTOC = { value = "out/extracted/protoc/bin/protoc", relative = true }

View File

@ -30,7 +30,8 @@
"qt/bundle/PyOxidizer", "qt/bundle/PyOxidizer",
"target", "target",
".mypy_cache", ".mypy_cache",
"extra" "extra",
"ts/.svelte-kit"
], ],
"plugins": [ "plugins": [
"https://plugins.dprint.dev/typescript-0.85.1.wasm", "https://plugins.dprint.dev/typescript-0.85.1.wasm",

View File

@ -36,6 +36,7 @@ module.exports = {
], ],
rules: { rules: {
"@typescript-eslint/no-non-null-assertion": "off", "@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-explicit-any": "off",
}, },
}, },
{ {
@ -47,11 +48,12 @@ module.exports = {
rules: { rules: {
"svelte/no-at-html-tags": "off", "svelte/no-at-html-tags": "off",
"svelte/valid-compile": ["error", { "ignoreWarnings": true }], "svelte/valid-compile": ["error", { "ignoreWarnings": true }],
"@typescript-eslint/no-explicit-any": "off",
}, },
}, },
], ],
env: { browser: true, es2020: true }, env: { browser: true, es2020: true },
ignorePatterns: ["backend_proto.d.ts", "*.svelte.d.ts", "vendor", "extra/*"], ignorePatterns: ["backend_proto.d.ts", "*.svelte.d.ts", "vendor", "extra/*", "vite.config.ts"],
globals: { globals: {
globalThis: false, globalThis: false,
NodeListOf: false, NodeListOf: false,

1
.gitignore vendored
View File

@ -15,3 +15,4 @@ node_modules
.ninja_deps .ninja_deps
/extra /extra
yarn-error.log yarn-error.log
ts/.svelte-kit

View File

@ -14,6 +14,7 @@ use ninja_gen::node::EsbuildScript;
use ninja_gen::node::TypescriptCheck; use ninja_gen::node::TypescriptCheck;
use ninja_gen::python::python_format; use ninja_gen::python::python_format;
use ninja_gen::python::PythonTest; use ninja_gen::python::PythonTest;
use ninja_gen::rsync::RsyncFiles;
use ninja_gen::Build; use ninja_gen::Build;
use ninja_gen::Utf8Path; use ninja_gen::Utf8Path;
use ninja_gen::Utf8PathBuf; use ninja_gen::Utf8PathBuf;
@ -21,7 +22,6 @@ use ninja_gen::Utf8PathBuf;
use crate::anki_version; use crate::anki_version;
use crate::python::BuildWheel; use crate::python::BuildWheel;
use crate::web::copy_mathjax; use crate::web::copy_mathjax;
use crate::web::eslint;
pub fn build_and_check_aqt(build: &mut Build) -> Result<()> { pub fn build_and_check_aqt(build: &mut Build) -> Result<()> {
build_forms(build)?; build_forms(build)?;
@ -114,9 +114,22 @@ fn build_data_folder(build: &mut Build) -> Result<()> {
build_js(build)?; build_js(build)?;
build_pages(build)?; build_pages(build)?;
build_icons(build)?; build_icons(build)?;
copy_sveltekit(build)?;
Ok(()) Ok(())
} }
fn copy_sveltekit(build: &mut Build) -> Result<()> {
build.add_action(
"qt:aqt:data:web:sveltekit",
RsyncFiles {
inputs: inputs![":sveltekit:folder"],
target_folder: "qt/_aqt/data/web/",
strip_prefix: "$builddir/",
extra_args: "-a",
},
)
}
fn build_css(build: &mut Build) -> Result<()> { fn build_css(build: &mut Build) -> Result<()> {
let scss_files = build.expand_inputs(inputs![glob!["qt/aqt/data/web/css/*.scss"]]); let scss_files = build.expand_inputs(inputs![glob!["qt/aqt/data/web/css/*.scss"]]);
let out_dir = Utf8Path::new("qt/_aqt/data/web/css"); let out_dir = Utf8Path::new("qt/_aqt/data/web/css");
@ -172,7 +185,6 @@ fn build_js(build: &mut Build) -> Result<()> {
)?; )?;
} }
let files = inputs![glob!["qt/aqt/data/web/js/*"]]; let files = inputs![glob!["qt/aqt/data/web/js/*"]];
eslint(build, "aqt", "qt/aqt/data/web/js", files.clone())?;
build.add_action( build.add_action(
"check:typescript:aqt", "check:typescript:aqt",
TypescriptCheck { TypescriptCheck {

View File

@ -56,8 +56,7 @@ fn prepare_translations(build: &mut Build) -> Result<()> {
], ],
outputs: &[ outputs: &[
RustOutput::Data("py", "pylib/anki/_fluent.py"), RustOutput::Data("py", "pylib/anki/_fluent.py"),
RustOutput::Data("ts", "ts/lib/ftl.d.ts"), RustOutput::Data("ts", "ts/lib/generated/ftl.ts"),
RustOutput::Data("ts", "ts/lib/ftl.js"),
], ],
target: None, target: None,
extra_args: "-p anki_i18n", extra_args: "-p anki_i18n",
@ -119,8 +118,7 @@ fn build_proto_descriptors_and_interfaces(build: &mut Build) -> Result<()> {
let outputs = vec![ let outputs = vec![
RustOutput::Data("descriptors.bin", "rslib/proto/descriptors.bin"), RustOutput::Data("descriptors.bin", "rslib/proto/descriptors.bin"),
RustOutput::Data("py", "pylib/anki/_backend_generated.py"), RustOutput::Data("py", "pylib/anki/_backend_generated.py"),
RustOutput::Data("ts", "ts/lib/backend.d.ts"), RustOutput::Data("ts", "ts/lib/generated/backend.ts"),
RustOutput::Data("ts", "ts/lib/backend.js"),
]; ];
build.add_action( build.add_action(
"rslib:proto", "rslib:proto",
@ -249,7 +247,7 @@ pub fn check_minilints(build: &mut Build) -> Result<()> {
let files = inputs![ let files = inputs![
glob![ glob![
"**/*.{py,rs,ts,svelte,mjs}", "**/*.{py,rs,ts,svelte,mjs}",
"{node_modules,qt/bundle/PyOxidizer}/**" "{node_modules,qt/bundle/PyOxidizer,ts/.svelte-kit}/**"
], ],
"Cargo.lock" "Cargo.lock"
]; ];

View File

@ -3,21 +3,21 @@
use anyhow::Result; use anyhow::Result;
use ninja_gen::action::BuildAction; use ninja_gen::action::BuildAction;
use ninja_gen::copy::CopyFiles;
use ninja_gen::glob; use ninja_gen::glob;
use ninja_gen::hashmap; use ninja_gen::hashmap;
use ninja_gen::input::BuildInput; use ninja_gen::input::BuildInput;
use ninja_gen::inputs; use ninja_gen::inputs;
use ninja_gen::node::node_archive; use ninja_gen::node::node_archive;
use ninja_gen::node::CompileSass; use ninja_gen::node::CompileSass;
use ninja_gen::node::CompileTypescript;
use ninja_gen::node::DPrint; use ninja_gen::node::DPrint;
use ninja_gen::node::EsbuildScript; use ninja_gen::node::EsbuildScript;
use ninja_gen::node::Eslint; use ninja_gen::node::Eslint;
use ninja_gen::node::GenTypescriptProto; use ninja_gen::node::GenTypescriptProto;
use ninja_gen::node::JestTest;
use ninja_gen::node::SqlFormat; use ninja_gen::node::SqlFormat;
use ninja_gen::node::SvelteCheck; use ninja_gen::node::SvelteCheck;
use ninja_gen::node::TypescriptCheck; use ninja_gen::node::SveltekitBuild;
use ninja_gen::node::ViteTest;
use ninja_gen::rsync::RsyncFiles; use ninja_gen::rsync::RsyncFiles;
use ninja_gen::Build; use ninja_gen::Build;
@ -25,6 +25,7 @@ pub fn build_and_check_web(build: &mut Build) -> Result<()> {
setup_node(build)?; setup_node(build)?;
build_sass(build)?; build_sass(build)?;
build_and_check_tslib(build)?; build_and_check_tslib(build)?;
build_sveltekit(build)?;
declare_and_check_other_libraries(build)?; declare_and_check_other_libraries(build)?;
build_and_check_pages(build)?; build_and_check_pages(build)?;
build_and_check_editor(build)?; build_and_check_editor(build)?;
@ -35,6 +36,20 @@ pub fn build_and_check_web(build: &mut Build) -> Result<()> {
Ok(()) Ok(())
} }
fn build_sveltekit(build: &mut Build) -> Result<()> {
build.add_action(
"sveltekit",
SveltekitBuild {
output_folder: inputs!["sveltekit"],
deps: inputs![
"ts/tsconfig.json",
glob!["ts/**", "ts/.svelte-kit/**"],
":ts:lib"
],
},
)
}
fn setup_node(build: &mut Build) -> Result<()> { fn setup_node(build: &mut Build) -> Result<()> {
ninja_gen::node::setup_node( ninja_gen::node::setup_node(
build, build,
@ -46,7 +61,8 @@ fn setup_node(build: &mut Build) -> Result<()> {
"sass", "sass",
"tsc", "tsc",
"tsx", "tsx",
"jest", "vite",
"vitest",
"protoc-gen-es", "protoc-gen-es",
], ],
hashmap! { hashmap! {
@ -111,55 +127,39 @@ fn setup_node(build: &mut Build) -> Result<()> {
} }
fn build_and_check_tslib(build: &mut Build) -> Result<()> { fn build_and_check_tslib(build: &mut Build) -> Result<()> {
build.add_dependency("ts:lib:i18n", ":rslib:i18n:ts".into()); build.add_dependency("ts:generated:i18n", ":rslib:i18n:ts".into());
build.add_action( build.add_action(
"ts:lib:proto", "ts:generated:proto",
GenTypescriptProto { GenTypescriptProto {
protos: inputs![glob!["proto/**/*.proto"]], protos: inputs![glob!["proto/**/*.proto"]],
include_dirs: &["proto"], include_dirs: &["proto"],
out_dir: "out/ts/lib", out_dir: "out/ts/lib/generated",
out_path_transform: |path| { out_path_transform: |path| {
path.replace("proto/", "ts/lib/") path.replace("proto/", "ts/lib/generated/")
.replace("proto\\", "ts/lib\\") .replace("proto\\", "ts/lib/generated\\")
}, },
ts_transform_script: "ts/tools/markpure.ts", ts_transform_script: "ts/tools/markpure.ts",
}, },
)?; )?;
// ensure _service files are generated by rslib // ensure _service files are generated by rslib
build.add_dependency("ts:lib:proto", inputs![":rslib:proto:ts"]); build.add_dependency("ts:generated:proto", inputs![":rslib:proto:ts"]);
// the generated _service.js files import @tslib/post, and esbuild won't be able // copy source files from ts/lib/generated
// to import the .ts file, so we need to generate a .js file for it
build.add_action( build.add_action(
"ts:lib:proto", "ts:generated:src",
CompileTypescript { CopyFiles {
ts_files: "ts/lib/post.ts".into(), inputs: inputs![glob!["ts/lib/generated/*.ts"]],
out_dir: "out/ts/lib", output_folder: "ts/lib/generated",
out_path_transform: |path| path.into(),
}, },
)?; )?;
let src_files = inputs![glob!["ts/lib/**"]]; let src_files = inputs![glob!["ts/lib/**"]];
eslint(build, "lib", "ts/lib", inputs![":ts:lib", &src_files])?;
build.add_action(
"check:jest:lib",
jest_test("ts/lib", inputs![":ts:lib", &src_files], true),
)?;
build.add_dependency("ts:lib", inputs![":ts:generated"]);
build.add_dependency("ts:lib", src_files); build.add_dependency("ts:lib", src_files);
Ok(()) Ok(())
} }
fn jest_test(folder: &str, deps: BuildInput, jsdom: bool) -> impl BuildAction + '_ {
JestTest {
folder,
deps,
jest_rc: "ts/jest.config.js".into(),
jsdom,
}
}
fn declare_and_check_other_libraries(build: &mut Build) -> Result<()> { fn declare_and_check_other_libraries(build: &mut Build) -> Result<()> {
for (library, inputs) in [ for (library, inputs) in [
("sveltelib", inputs![":ts:lib", glob!("ts/sveltelib/**")]), ("sveltelib", inputs![":ts:lib", glob!("ts/sveltelib/**")]),
@ -171,49 +171,13 @@ fn declare_and_check_other_libraries(build: &mut Build) -> Result<()> {
("html-filter", inputs![glob!("ts/html-filter/**")]), ("html-filter", inputs![glob!("ts/html-filter/**")]),
] { ] {
let library_with_ts = format!("ts:{library}"); let library_with_ts = format!("ts:{library}");
let folder = library_with_ts.replace(':', "/");
build.add_dependency(&library_with_ts, inputs.clone()); build.add_dependency(&library_with_ts, inputs.clone());
eslint(build, library, &folder, inputs.clone())?;
if matches!(library, "domlib" | "html-filter") {
build.add_action(
&format!("check:jest:{library}"),
jest_test(&folder, inputs, true),
)?;
}
} }
eslint(build, "scripts", "ts/tools", inputs![glob!("ts/tools/*")])?;
Ok(())
}
pub fn eslint(build: &mut Build, name: &str, folder: &str, deps: BuildInput) -> Result<()> {
let eslint_rc = inputs![".eslintrc.js"];
build.add_action(
format!("check:eslint:{name}"),
Eslint {
folder,
inputs: deps.clone(),
eslint_rc: eslint_rc.clone(),
fix: false,
},
)?;
build.add_action(
format!("fix:eslint:{name}"),
Eslint {
folder,
inputs: deps,
eslint_rc,
fix: true,
},
)?;
Ok(()) Ok(())
} }
fn build_and_check_pages(build: &mut Build) -> Result<()> { fn build_and_check_pages(build: &mut Build) -> Result<()> {
build.add_dependency("ts:tag-editor", inputs![glob!["ts/tag-editor/**"]]);
let mut build_page = |name: &str, html: bool, deps: BuildInput| -> Result<()> { let mut build_page = |name: &str, html: bool, deps: BuildInput| -> Result<()> {
let group = format!("ts:{name}"); let group = format!("ts:{name}");
let deps = inputs![deps, glob!(format!("ts/{name}/**"))]; let deps = inputs![deps, glob!(format!("ts/{name}/**"))];
@ -229,99 +193,9 @@ fn build_and_check_pages(build: &mut Build) -> Result<()> {
}, },
)?; )?;
build.add_dependency("ts:pages", inputs![format!(":{group}")]); build.add_dependency("ts:pages", inputs![format!(":{group}")]);
build.add_action(
format!("check:svelte:{name}"),
SvelteCheck {
tsconfig: inputs![format!("ts/{name}/tsconfig.json")],
inputs: deps.clone(),
},
)?;
let folder = format!("ts/{name}");
eslint(build, name, &folder, deps.clone())?;
if matches!(name, "deck-options" | "change-notetype") {
build.add_action(
&format!("check:jest:{name}"),
jest_test(&folder, deps, false),
)?;
}
Ok(()) Ok(())
}; };
build_page(
"congrats",
true,
inputs![
//
":ts:lib",
":ts:components",
":sass",
],
)?;
build_page(
"deck-options",
true,
inputs![
//
":ts:lib",
":ts:components",
":ts:sveltelib",
":sass",
],
)?;
build_page(
"graphs",
true,
inputs![
//
":ts:lib",
":ts:components",
":sass",
],
)?;
build_page(
"card-info",
true,
inputs![
//
":ts:lib",
":ts:components",
":sass",
],
)?;
build_page(
"change-notetype",
true,
inputs![
//
":ts:lib",
":ts:components",
":ts:sveltelib",
":sass",
],
)?;
build_page(
"import-csv",
true,
inputs![
//
":ts:lib",
":ts:components",
":ts:sveltelib",
":ts:tag-editor",
":sass"
],
)?;
build_page(
"import-anki-package",
true,
inputs![
//
":ts:lib",
":ts:components",
":ts:sveltelib",
":sass"
],
)?;
// we use the generated .css file separately // we use the generated .css file separately
build_page( build_page(
"editable", "editable",
@ -332,30 +206,8 @@ fn build_and_check_pages(build: &mut Build) -> Result<()> {
":ts:components", ":ts:components",
":ts:domlib", ":ts:domlib",
":ts:sveltelib", ":ts:sveltelib",
":sass" ":sass",
], ":sveltekit",
)?;
build_page(
"image-occlusion",
true,
inputs![
//
":ts:lib",
":ts:components",
":ts:sveltelib",
":ts:tag-editor",
":sass"
],
)?;
build_page(
"import-page",
true,
inputs![
//
":ts:lib",
":ts:components",
":ts:sveltelib",
":sass"
], ],
)?; )?;
@ -369,11 +221,10 @@ fn build_and_check_editor(build: &mut Build) -> Result<()> {
":ts:components", ":ts:components",
":ts:domlib", ":ts:domlib",
":ts:sveltelib", ":ts:sveltelib",
":ts:tag-editor",
":ts:html-filter", ":ts:html-filter",
":ts:image-occlusion",
":sass", ":sass",
glob!("ts/{editable,editor}/**") ":sveltekit",
glob!("ts/{editable,editor,routes/image-occlusion}/**")
]; ];
build.add_action( build.add_action(
@ -387,20 +238,15 @@ fn build_and_check_editor(build: &mut Build) -> Result<()> {
}, },
)?; )?;
let group = "ts/editor";
build.add_action(
"check:svelte:editor",
SvelteCheck {
tsconfig: inputs![format!("{group}/tsconfig.json")],
inputs: editor_deps.clone(),
},
)?;
eslint(build, "editor", group, editor_deps)?;
Ok(()) Ok(())
} }
fn build_and_check_reviewer(build: &mut Build) -> Result<()> { fn build_and_check_reviewer(build: &mut Build) -> Result<()> {
let reviewer_deps = inputs![":ts:lib", glob!("ts/{reviewer,image-occlusion}/**"),]; let reviewer_deps = inputs![
":ts:lib",
glob!("ts/{reviewer,image-occlusion}/**"),
":sveltekit"
];
build.add_action( build.add_action(
"ts:reviewer:reviewer.js", "ts:reviewer:reviewer.js",
EsbuildScript { EsbuildScript {
@ -416,7 +262,7 @@ fn build_and_check_reviewer(build: &mut Build) -> Result<()> {
CompileSass { CompileSass {
input: inputs!["ts/reviewer/reviewer.scss"], input: inputs!["ts/reviewer/reviewer.scss"],
output: "ts/reviewer/reviewer.css", output: "ts/reviewer/reviewer.css",
deps: inputs![":sass", "ts/image-occlusion/review.scss"], deps: inputs![":sass", "ts/routes/image-occlusion/review.scss"],
load_paths: vec!["."], load_paths: vec!["."],
}, },
)?; )?;
@ -435,30 +281,18 @@ fn build_and_check_reviewer(build: &mut Build) -> Result<()> {
CompileSass { CompileSass {
input: inputs!["ts/reviewer/reviewer_extras.scss"], input: inputs!["ts/reviewer/reviewer_extras.scss"],
output: "ts/reviewer/reviewer_extras.css", output: "ts/reviewer/reviewer_extras.css",
deps: inputs!["ts/image-occlusion/review.scss"], deps: inputs!["ts/routes/image-occlusion/review.scss"],
load_paths: vec!["."], load_paths: vec!["."],
}, },
)?; )?;
build.add_action(
"check:typescript:reviewer",
TypescriptCheck {
tsconfig: inputs!["ts/reviewer/tsconfig.json"],
inputs: reviewer_deps.clone(),
},
)?;
eslint(build, "reviewer", "ts/reviewer", reviewer_deps)?;
build.add_action(
"check:jest:reviewer",
jest_test("ts/reviewer", inputs![":ts:reviewer"], false),
)?;
Ok(()) Ok(())
} }
fn check_web(build: &mut Build) -> Result<()> { fn check_web(build: &mut Build) -> Result<()> {
let dprint_files = inputs![glob![ let dprint_files = inputs![glob![
"**/*.{ts,mjs,js,md,json,toml,svelte,scss}", "**/*.{ts,mjs,js,md,json,toml,svelte,scss}",
"target/**" "{target,ts/.svelte-kit}/**"
]]; ]];
build.add_action( build.add_action(
"check:format:dprint", "check:format:dprint",
@ -474,6 +308,52 @@ fn check_web(build: &mut Build) -> Result<()> {
check_only: false, check_only: false,
}, },
)?; )?;
build.add_action(
"check:vitest",
ViteTest {
deps: inputs![
"yarn",
":node_modules",
":ts:generated",
glob!["ts/{svelte.config.js,vite.config.ts,tsconfig.json}"],
glob!["ts/{lib,deck-options,html-filter,domlib,reviewer,change-notetype}/**/*"],
],
},
)?;
build.add_action(
"check:svelte",
SvelteCheck {
tsconfig: inputs!["ts/tsconfig.json"],
inputs: inputs![
"yarn",
":node_modules",
":ts:generated",
glob!["ts/**/*", "ts/.svelte-kit/**"],
],
},
)?;
let eslint_rc = inputs![".eslintrc.cjs"];
for folder in ["ts", "qt/aqt/data/web/js"] {
let inputs = inputs![glob![format!("{folder}/**"), "ts/.svelte-kit/**"]];
build.add_action(
"check:eslint",
Eslint {
folder,
inputs: inputs.clone(),
eslint_rc: eslint_rc.clone(),
fix: false,
},
)?;
build.add_action(
"fix:eslint",
Eslint {
folder,
inputs,
eslint_rc: eslint_rc.clone(),
fix: true,
},
)?;
}
Ok(()) Ok(())
} }
@ -497,7 +377,7 @@ pub fn check_sql(build: &mut Build) -> Result<()> {
} }
fn build_and_check_mathjax(build: &mut Build) -> Result<()> { fn build_and_check_mathjax(build: &mut Build) -> Result<()> {
let files = inputs![glob!["ts/mathjax/*"]]; let files = inputs![glob!["ts/mathjax/*"], ":sveltekit"];
build.add_action( build.add_action(
"ts:mathjax", "ts:mathjax",
EsbuildScript { EsbuildScript {
@ -507,14 +387,6 @@ fn build_and_check_mathjax(build: &mut Build) -> Result<()> {
output_stem: "ts/mathjax/mathjax", output_stem: "ts/mathjax/mathjax",
extra_exts: &[], extra_exts: &[],
}, },
)?;
eslint(build, "mathjax", "ts/mathjax", files.clone())?;
build.add_action(
"check:typescript:mathjax",
TypescriptCheck {
tsconfig: "ts/mathjax/tsconfig.json".into(),
inputs: files,
},
) )
} }
@ -566,14 +438,14 @@ pub fn copy_mathjax() -> impl BuildAction {
} }
fn build_sass(build: &mut Build) -> Result<()> { fn build_sass(build: &mut Build) -> Result<()> {
build.add_dependency("sass", inputs![glob!("sass/**")]); build.add_dependency("sass", inputs![glob!("ts/lib/sass/**")]);
build.add_action( build.add_action(
"css:_root-vars", "css:_root-vars",
CompileSass { CompileSass {
input: inputs!["sass/_root-vars.scss"], input: inputs!["ts/lib/sass/_root-vars.scss"],
output: "sass/_root-vars.css", output: "ts/lib/sass/_root-vars.css",
deps: inputs![glob!["sass/*"]], deps: inputs![glob!["ts/lib/sass/*"]],
load_paths: vec![], load_paths: vec![],
}, },
)?; )?;

View File

@ -19,24 +19,24 @@ use crate::input::BuildInput;
pub fn node_archive(platform: Platform) -> OnlineArchive { pub fn node_archive(platform: Platform) -> OnlineArchive {
match platform { match platform {
Platform::LinuxX64 => OnlineArchive { Platform::LinuxX64 => OnlineArchive {
url: "https://nodejs.org/dist/v18.12.1/node-v18.12.1-linux-x64.tar.xz", url: "https://nodejs.org/dist/v20.11.0/node-v20.11.0-linux-x64.tar.xz",
sha256: "4481a34bf32ddb9a9ff9540338539401320e8c3628af39929b4211ea3552a19e", sha256: "822780369d0ea309e7d218e41debbd1a03f8cdf354ebf8a4420e89f39cc2e612",
}, },
Platform::LinuxArm => OnlineArchive { Platform::LinuxArm => OnlineArchive {
url: "https://nodejs.org/dist/v18.12.1/node-v18.12.1-linux-arm64.tar.xz", url: "https://nodejs.org/dist/v20.11.0/node-v20.11.0-linux-arm64.tar.xz",
sha256: "3904869935b7ecc51130b4b86486d2356539a174d11c9181180cab649f32cd2a", sha256: "f943abd348d2b8ff8754ca912c118a20301eb6a0014cc4cdea86cff021fde8e6",
}, },
Platform::MacX64 => OnlineArchive { Platform::MacX64 => OnlineArchive {
url: "https://nodejs.org/dist/v18.12.1/node-v18.12.1-darwin-x64.tar.xz", url: "https://nodejs.org/dist/v20.11.0/node-v20.11.0-darwin-x64.tar.xz",
sha256: "6c88d462550a024661e74e9377371d7e023321a652eafb3d14d58a866e6ac002", sha256: "d4b4ab81ebf1f7aab09714f834992f27270ad0079600da00c8110f8950ca6c5a",
}, },
Platform::MacArm => OnlineArchive { Platform::MacArm => OnlineArchive {
url: "https://nodejs.org/dist/v18.12.1/node-v18.12.1-darwin-arm64.tar.xz", url: "https://nodejs.org/dist/v20.11.0/node-v20.11.0-darwin-arm64.tar.xz",
sha256: "17f2e25d207d36d6b0964845062160d9ed16207c08d09af33b9a2fd046c5896f", sha256: "f18a7438723d48417f5e9be211a2f3c0520ffbf8e02703469e5153137ca0f328",
}, },
Platform::WindowsX64 => OnlineArchive { Platform::WindowsX64 => OnlineArchive {
url: "https://nodejs.org/dist/v18.12.1/node-v18.12.1-win-x64.zip", url: "https://nodejs.org/dist/v20.11.0/node-v20.11.0-win-x64.zip",
sha256: "5478a5a2dce2803ae22327a9f8ae8494c1dec4a4beca5bbf897027380aecf4c7", sha256: "893115cd92ad27bf178802f15247115e93c0ef0c753b93dca96439240d64feb5",
}, },
} }
} }
@ -214,9 +214,11 @@ pub struct SvelteCheck {
impl BuildAction for SvelteCheck { impl BuildAction for SvelteCheck {
fn command(&self) -> &str { fn command(&self) -> &str {
"$svelte-check --tsconfig $tsconfig $ if cfg!(windows) {
--fail-on-warnings --threshold warning $ "cmd /c yarn svelte-check:once"
--compiler-warnings $compiler_warnings" } else {
"./yarn svelte-check:once"
}
} }
fn files(&mut self, build: &mut impl build::FilesHandle) { fn files(&mut self, build: &mut impl build::FilesHandle) {
@ -290,30 +292,23 @@ impl BuildAction for Eslint<'_> {
} }
} }
pub struct JestTest<'a> { pub struct ViteTest {
pub folder: &'a str,
pub deps: BuildInput, pub deps: BuildInput,
pub jest_rc: BuildInput,
pub jsdom: bool,
} }
impl BuildAction for JestTest<'_> { impl BuildAction for ViteTest {
fn command(&self) -> &str { fn command(&self) -> &str {
"$jest --config $config $env $folder" if cfg!(windows) {
"cmd /c yarn vitest:once"
} else {
"./yarn vitest:once"
}
} }
fn files(&mut self, build: &mut impl build::FilesHandle) { fn files(&mut self, build: &mut impl build::FilesHandle) {
build.add_inputs("jest", inputs![":node_modules:jest"]); build.add_inputs("vitest", inputs![":node_modules:vitest"]);
build.add_inputs("", &self.deps); build.add_inputs("", &self.deps);
build.add_inputs("config", &self.jest_rc); build.add_output_stamp("tests/vitest");
build.add_variable("env", if self.jsdom { "--env=jsdom" } else { "" });
build.add_variable("folder", self.folder);
let hash = simple_hash(self.folder);
build.add_output_stamp(format!("tests/jest.{hash}"));
}
fn hide_last_line(&self) -> bool {
true
} }
} }
@ -451,3 +446,32 @@ impl BuildAction for CompileTypescript<'_> {
build.add_outputs("", output_files); build.add_outputs("", output_files);
} }
} }
/// The output_folder will be declared as a build output, but each file inside
/// it is not declared, as the files will vary.
pub struct SveltekitBuild {
pub output_folder: BuildInput,
pub deps: BuildInput,
}
impl BuildAction for SveltekitBuild {
fn command(&self) -> &str {
if std::env::var("HMR").is_err() {
if cfg!(windows) {
"cmd /c yarn build"
} else {
"./yarn build"
}
} else {
"echo"
}
}
fn files(&mut self, build: &mut impl build::FilesHandle) {
build.add_inputs("node_modules", inputs![":node_modules"]);
build.add_inputs("", &self.deps);
build.add_inputs("", inputs!["yarn.lock"]);
build.add_output_stamp("sveltekit.marker");
build.add_outputs_ext("folder", vec!["sveltekit"], true);
}
}

View File

@ -69,11 +69,7 @@ pub fn run_build(args: BuildArgs) {
// commands will not show colors by default, as we do not provide a tty // commands will not show colors by default, as we do not provide a tty
.env("FORCE_COLOR", "1") .env("FORCE_COLOR", "1")
.env("MYPY_FORCE_COLOR", "1") .env("MYPY_FORCE_COLOR", "1")
.env("TERM", std::env::var("TERM").unwrap_or_default()) .env("TERM", std::env::var("TERM").unwrap_or_default());
// Prevents 'Warn: You must provide the URL of lib/mappings.wasm'.
// Updating svelte-check or its deps will likely remove the need for it.
.env("NODE_OPTIONS", "--no-experimental-fetch");
if env::var("NINJA_STATUS").is_err() { if env::var("NINJA_STATUS").is_err() {
command.env("NINJA_STATUS", "[%f/%t; %r active; %es] "); command.env("NINJA_STATUS", "[%f/%t; %r active; %es] ");
} }

2
ninja
View File

@ -8,7 +8,7 @@ else
out="$BUILD_ROOT" out="$BUILD_ROOT"
fi fi
export CARGO_TARGET_DIR=$out/rust export CARGO_TARGET_DIR=$out/rust
export RECONFIGURE_KEY="${MAC_X86};${SOURCEMAP}" export RECONFIGURE_KEY="${MAC_X86};${SOURCEMAP};${HMR}"
if [ "$SKIP_RUNNER_BUILD" = "1" ]; then if [ "$SKIP_RUNNER_BUILD" = "1" ]; then
echo "Runner not rebuilt." echo "Runner not rebuilt."

View File

@ -5,14 +5,26 @@
"author": "Ankitects Pty Ltd and contributors", "author": "Ankitects Pty Ltd and contributors",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"description": "Anki JS support files", "description": "Anki JS support files",
"scripts": {
"dev": "cd ts && vite dev",
"build": "cd ts && vite build",
"preview": "cd ts && vite preview",
"svelte-check:once": "cd ts && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --fail-on-warnings --threshold warning --compiler-warnings a11y-click-events-have-key-events:ignore,a11y-no-noninteractive-tabindex:ignore,a11y-no-static-element-interactions:ignore",
"svelte-check": "cd ts && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch --compiler-warnings a11y-click-events-have-key-events:ignore,a11y-no-noninteractive-tabindex:ignore,a11y-no-static-element-interactions:ignore",
"vitest:once": "cd ts && vitest run",
"vitest": "cd ts && vitest"
},
"devDependencies": { "devDependencies": {
"@bufbuild/protoc-gen-es": "^1.2.1", "@bufbuild/protoc-gen-es": "^1.8.0",
"@sqltools/formatter": "^1.2.2", "@sqltools/formatter": "^1.2.2",
"@sveltejs/adapter-static": "^3.0.0",
"@sveltejs/kit": "^2.4.1",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"@types/bootstrap": "^5.0.12", "@types/bootstrap": "^5.0.12",
"@types/codemirror": "^5.60.0", "@types/codemirror": "^5.60.0",
"@types/d3": "^7.0.0", "@types/d3": "^7.0.0",
"@types/diff": "^5.0.0", "@types/diff": "^5.0.0",
"@types/jest": "^27.0.2", "@types/fabric": "^5.3.7",
"@types/jquery": "^3.5.0", "@types/jquery": "^3.5.0",
"@types/jqueryui": "^1.12.13", "@types/jqueryui": "^1.12.13",
"@types/lodash-es": "^4.17.4", "@types/lodash-es": "^4.17.4",
@ -32,8 +44,6 @@
"eslint-plugin-import": "^2.25.4", "eslint-plugin-import": "^2.25.4",
"eslint-plugin-simple-import-sort": "^10.0.0", "eslint-plugin-simple-import-sort": "^10.0.0",
"eslint-plugin-svelte": "^2", "eslint-plugin-svelte": "^2",
"jest-cli": "^28.0.0-alpha.5",
"jest-environment-jsdom": "^28.0.0-alpha.5",
"license-checker-rseidelsohn": "^4.2.6", "license-checker-rseidelsohn": "^4.2.6",
"prettier": "^2.4.1", "prettier": "^2.4.1",
"prettier-plugin-svelte": "^2.10.1", "prettier-plugin-svelte": "^2.10.1",
@ -43,7 +53,9 @@
"svelte-preprocess-esbuild": "^3.0.1", "svelte-preprocess-esbuild": "^3.0.1",
"tslib": "^2.0.3", "tslib": "^2.0.3",
"tsx": "^3.12.0", "tsx": "^3.12.0",
"typescript": "^5.0.4" "typescript": "^5.0.4",
"vite": "^5.0.12",
"vitest": "^1.2.1"
}, },
"dependencies": { "dependencies": {
"@bufbuild/protobuf": "^1.2.1", "@bufbuild/protobuf": "^1.2.1",
@ -74,5 +86,6 @@
"not < 1%", "not < 1%",
"Chrome 77", "Chrome 77",
"iOS 14.5" "iOS 14.5"
] ],
"type": "module"
} }

View File

@ -248,6 +248,7 @@ is_win = sys.platform.startswith("win32")
# also covers *BSD # also covers *BSD
is_lin = not is_mac and not is_win is_lin = not is_mac and not is_win
dev_mode = os.getenv("ANKIDEV", "") dev_mode = os.getenv("ANKIDEV", "")
hmr_mode = os.getenv("HMR", "")
INVALID_FILENAME_CHARS = ':*?"<>|' INVALID_FILENAME_CHARS = ':*?"<>|'

View File

@ -3,7 +3,6 @@
from __future__ import annotations from __future__ import annotations
import json
from typing import Callable from typing import Callable
import aqt import aqt
@ -55,7 +54,7 @@ class CardInfoDialog(QDialog):
self.web = AnkiWebView(kind=AnkiWebViewKind.BROWSER_CARD_INFO) self.web = AnkiWebView(kind=AnkiWebViewKind.BROWSER_CARD_INFO)
self.web.setVisible(False) self.web.setVisible(False)
self.web.load_ts_page("card-info") self.web.load_sveltekit_page(f"card-info/{card_id}")
layout = QVBoxLayout() layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0) layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(self.web) layout.addWidget(self.web)
@ -64,17 +63,13 @@ class CardInfoDialog(QDialog):
layout.addWidget(buttons) layout.addWidget(buttons)
qconnect(buttons.rejected, self.reject) qconnect(buttons.rejected, self.reject)
self.setLayout(layout) self.setLayout(layout)
self.web.eval("anki.cardInfoPromise = anki.setupCardInfo(document.body);")
self.update_card(card_id)
def update_card(self, card_id: CardId | None) -> None: def update_card(self, card_id: CardId | None) -> None:
try: try:
self.mw.col.get_card(card_id) self.mw.col.get_card(card_id)
except NotFoundError: except NotFoundError:
card_id = None card_id = None
self.web.eval( self.web.eval(f"window.location.href = '/card-info/{card_id}';")
f"anki.cardInfoPromise.then((c) => c.updateStats({json.dumps(card_id)}));"
)
def reject(self) -> None: def reject(self) -> None:
if self._on_close: if self._on_close:

View File

@ -53,15 +53,12 @@ class ChangeNotetypeDialog(QDialog):
self.web = AnkiWebView(kind=AnkiWebViewKind.CHANGE_NOTETYPE) self.web = AnkiWebView(kind=AnkiWebViewKind.CHANGE_NOTETYPE)
self.web.setVisible(False) self.web.setVisible(False)
self.web.load_ts_page("change-notetype") self.web.load_sveltekit_page(f"change-notetype/{notetype_id}")
layout = QVBoxLayout() layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0) layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(self.web) layout.addWidget(self.web)
self.setLayout(layout) self.setLayout(layout)
self.web.eval(
f"""anki.setupChangeNotetypePage({notetype_id}, {notetype_id});"""
)
self.setWindowTitle(tr.browsing_change_notetype()) self.setWindowTitle(tr.browsing_change_notetype())
def reject(self) -> None: def reject(self) -> None:

View File

@ -1,9 +1,9 @@
/* Copyright: Ankitects Pty Ltd and contributors /* Copyright: Ankitects Pty Ltd and contributors
* License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */ * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */
@use "sass/root-vars"; @use "../../../../../ts/lib/sass/root-vars";
@use "sass/vars" as *; @use "../../../../../ts/lib/sass/vars" as *;
@use "sass/card-counts"; @use "../../../../../ts/lib/sass/card-counts";
@use "sass/elevation" as *; @use "../../../../../ts/lib/sass/elevation" as *;
table { table {
padding: 1rem; padding: 1rem;

View File

@ -1,10 +1,10 @@
/* Copyright: Ankitects Pty Ltd and contributors /* Copyright: Ankitects Pty Ltd and contributors
* License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */ * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */
@use "sass/root-vars"; @use "../../../../../ts/lib/sass/root-vars";
@use "sass/vars" as *; @use "../../../../../ts/lib/sass/vars" as *;
@use "sass/card-counts"; @use "../../../../../ts/lib/sass/card-counts";
@use "sass/button-mixins" as button; @use "../../../../../ts/lib/sass/button-mixins" as button;
.smallLink { .smallLink {
font-size: 10px; font-size: 10px;

View File

@ -1,9 +1,9 @@
/* Copyright: Ankitects Pty Ltd and contributors /* Copyright: Ankitects Pty Ltd and contributors
* License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */ * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */
@use "sass/root-vars"; @use "../../../../../ts/lib/sass/root-vars";
@use "sass/vars" as *; @use "../../../../../ts/lib/sass/vars" as *;
@use "sass/card-counts"; @use "../../../../../ts/lib/sass/card-counts";
:root { :root {
--focus-color: #{palette-of(border-focus)}; --focus-color: #{palette-of(border-focus)};

View File

@ -1,10 +1,10 @@
/* Copyright: Ankitects Pty Ltd and contributors /* Copyright: Ankitects Pty Ltd and contributors
* License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */ * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */
@use "sass/root-vars"; @use "../../../../../ts/lib/sass/root-vars";
@use "sass/vars" as *; @use "../../../../../ts/lib/sass/vars" as *;
@use "sass/elevation" as *; @use "../../../../../ts/lib/sass/elevation" as *;
@use "sass/button-mixins" as button; @use "../../../../../ts/lib/sass/button-mixins" as button;
.header { .header {
display: grid; display: grid;

View File

@ -1,9 +1,9 @@
/* Copyright: Ankitects Pty Ltd and contributors /* Copyright: Ankitects Pty Ltd and contributors
* License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */ * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */
@use "sass/root-vars"; @use "../../../../../ts/lib/sass/root-vars";
@use "sass/scrollbar"; @use "../../../../../ts/lib/sass/scrollbar";
@use "sass/buttons"; @use "../../../../../ts/lib/sass/buttons";
* { * {
// border-box would be better, but we need to // border-box would be better, but we need to

View File

@ -1,5 +1,5 @@
{ {
"extends": "../../../../../ts/tsconfig.json", "extends": "../../../../../ts/tsconfig_legacy.json",
"include": ["*.ts"], "include": ["*.ts"],
"references": [], "references": [],
"compilerOptions": { "compilerOptions": {

View File

@ -43,17 +43,13 @@ class DeckOptionsDialog(QDialog):
addCloseShortcut(self) addCloseShortcut(self)
self.web = AnkiWebView(kind=AnkiWebViewKind.DECK_OPTIONS) self.web = AnkiWebView(kind=AnkiWebViewKind.DECK_OPTIONS)
self.web.load_ts_page("deck-options") self.web.load_sveltekit_page(f"deck-options/{self._deck['id']}")
layout = QVBoxLayout() layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0) layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(self.web) layout.addWidget(self.web)
self.setLayout(layout) self.setLayout(layout)
self.show() self.show()
self.web.hide_while_preserving_layout() self.web.hide_while_preserving_layout()
self.web.eval(
f"""const $deckOptions = anki.setupDeckOptions({self._deck["id"]});"""
)
self.setWindowTitle( self.setWindowTitle(
without_unicode_isolation(tr.actions_options_for(val=self._deck["name"])) without_unicode_isolation(tr.actions_options_for(val=self._deck["name"]))
) )

View File

@ -21,7 +21,6 @@ class ImportArgs:
title = "importLog" title = "importLog"
kind = AnkiWebViewKind.IMPORT_LOG kind = AnkiWebViewKind.IMPORT_LOG
ts_page = "import-page" ts_page = "import-page"
setup_function_name = "setupImportPage"
def args_json(self) -> str: def args_json(self) -> str:
return json.dumps(self.path) return json.dumps(self.path)
@ -32,26 +31,16 @@ class JsonFileArgs(ImportArgs):
return json.dumps(dict(type="json_file", path=self.path)) return json.dumps(dict(type="json_file", path=self.path))
@dataclass
class JsonStringArgs(ImportArgs):
json: str
def args_json(self) -> str:
return json.dumps(dict(type="json_string", path=self.path, json=self.json))
class CsvArgs(ImportArgs): class CsvArgs(ImportArgs):
title = "csv import" title = "csv import"
kind = AnkiWebViewKind.IMPORT_CSV kind = AnkiWebViewKind.IMPORT_CSV
ts_page = "import-csv" ts_page = "import-csv"
setup_function_name = "setupImportCsvPage"
class AnkiPackageArgs(ImportArgs): class AnkiPackageArgs(ImportArgs):
title = "anki package import" title = "anki package import"
kind = AnkiWebViewKind.IMPORT_ANKI_PACKAGE kind = AnkiWebViewKind.IMPORT_ANKI_PACKAGE
ts_page = "import-anki-package" ts_page = "import-anki-package"
setup_function_name = "setupImportAnkiPackagePage"
class ImportDialog(QDialog): class ImportDialog(QDialog):
@ -76,17 +65,13 @@ class ImportDialog(QDialog):
self.web = AnkiWebView(kind=self.args.kind) self.web = AnkiWebView(kind=self.args.kind)
self.web.setVisible(False) self.web.setVisible(False)
self.web.load_ts_page(self.args.ts_page) self.web.load_sveltekit_page(f"{self.args.ts_page}/{self.args.path}")
layout = QVBoxLayout() layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0) layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(self.web) layout.addWidget(self.web)
self.setLayout(layout) self.setLayout(layout)
restoreGeom(self, self.args.title, default_size=(800, 800)) restoreGeom(self, self.args.title, default_size=(800, 800))
self.web.evalWithCallback(
f"anki.{self.args.setup_function_name}({self.args.args_json()});",
lambda _: self.web.setFocus(),
)
self.setWindowTitle(tr.decks_import_file()) self.setWindowTitle(tr.decks_import_file())
def reject(self) -> None: def reject(self) -> None:

View File

@ -13,12 +13,12 @@ from anki.collection import Collection, Progress
from anki.errors import Interrupted from anki.errors import Interrupted
from anki.foreign_data import mnemosyne from anki.foreign_data import mnemosyne
from anki.lang import without_unicode_isolation from anki.lang import without_unicode_isolation
from anki.utils import tmpdir
from aqt.import_export.import_dialog import ( from aqt.import_export.import_dialog import (
AnkiPackageArgs, AnkiPackageArgs,
CsvArgs, CsvArgs,
ImportDialog, ImportDialog,
JsonFileArgs, JsonFileArgs,
JsonStringArgs,
) )
from aqt.operations import QueryOp from aqt.operations import QueryOp
from aqt.progress import ProgressUpdate from aqt.progress import ProgressUpdate
@ -95,10 +95,16 @@ class MnemosyneImporter(Importer):
@staticmethod @staticmethod
def do_import(mw: aqt.main.AnkiQt, path: str) -> None: def do_import(mw: aqt.main.AnkiQt, path: str) -> None:
def on_success(json: str) -> None:
json_path = os.path.join(tmpdir(), path)
with open(json_path, "wb") as file:
file.write(json.encode("utf8"))
ImportDialog(mw, JsonFileArgs(path=json_path))
QueryOp( QueryOp(
parent=mw, parent=mw,
op=lambda col: mnemosyne.serialize(path, col.decks.current()["id"]), op=lambda col: mnemosyne.serialize(path, col.decks.current()["id"]),
success=lambda json: ImportDialog(mw, JsonStringArgs(path=path, json=json)), success=on_success,
).with_progress().run_in_background() ).with_progress().run_in_background()

View File

@ -109,6 +109,7 @@ class MainWebView(AnkiWebView):
self.setFocusPolicy(Qt.FocusPolicy.WheelFocus) self.setFocusPolicy(Qt.FocusPolicy.WheelFocus)
self.setMinimumWidth(400) self.setMinimumWidth(400)
self.setAcceptDrops(True) self.setAcceptDrops(True)
print("todo: windows paths in import screen")
# Importing files via drag & drop # Importing files via drag & drop
########################################################################## ##########################################################################

View File

@ -166,7 +166,7 @@ def _mime_for_path(path: str) -> str:
if path.endswith(".css"): if path.endswith(".css"):
# some users may have invalid mime type in the Windows registry # some users may have invalid mime type in the Windows registry
return "text/css" return "text/css"
elif path.endswith(".js"): elif path.endswith(".js") or path.endswith(".mjs"):
return "application/javascript" return "application/javascript"
else: else:
# autodetect # autodetect
@ -255,11 +255,18 @@ def _builtin_data(path: str) -> bytes:
def _handle_builtin_file_request(request: BundledFileRequest) -> Response: def _handle_builtin_file_request(request: BundledFileRequest) -> Response:
path = request.path path = request.path
# do we need to serve the fallback page?
immutable = "immutable" in path
if path.startswith("sveltekit/") and not immutable:
path = "sveltekit/index.html"
mimetype = _mime_for_path(path) mimetype = _mime_for_path(path)
data_path = f"data/web/{path}" data_path = f"data/web/{path}"
try: try:
data = _builtin_data(data_path) data = _builtin_data(data_path)
return Response(data, mimetype=mimetype) response = Response(data, mimetype=mimetype)
if immutable:
response.headers["Cache-Control"] = "max-age=31536000"
return response
except FileNotFoundError: except FileNotFoundError:
if dev_mode: if dev_mode:
print(f"404: {data_path}") print(f"404: {data_path}")
@ -316,10 +323,29 @@ def handle_request(pathin: str) -> Response:
) )
def is_sveltekit_page(path: str) -> bool:
page_name = path.split("/")[0]
return page_name in [
"graphs",
"congrats",
"card-info",
"change-notetype",
"deck-options",
"import-anki-package",
"import-csv",
"import-page",
]
def _extract_internal_request( def _extract_internal_request(
path: str, path: str,
) -> BundledFileRequest | DynamicRequest | NotFound | None: ) -> BundledFileRequest | DynamicRequest | NotFound | None:
"Catch /_anki references and rewrite them to web export folder." "Catch /_anki references and rewrite them to web export folder."
if is_sveltekit_page(path):
path = f"_anki/sveltekit/_app/{path}"
if path.startswith("_app/"):
path = path.replace("_app", "_anki/sveltekit/_app")
prefix = "_anki/" prefix = "_anki/"
if not path.startswith(prefix): if not path.startswith(prefix):
return None return None
@ -662,6 +688,7 @@ def _check_dynamic_request_permissions():
context == PageContext.NON_LEGACY_PAGE context == PageContext.NON_LEGACY_PAGE
or context == PageContext.EDITOR or context == PageContext.EDITOR
or context == PageContext.ADDON_PAGE or context == PageContext.ADDON_PAGE
or os.environ.get("ANKI_API_PORT")
): ):
pass pass
elif context == PageContext.REVIEWER and request.path in ( elif context == PageContext.REVIEWER and request.path in (
@ -698,7 +725,7 @@ def _extract_page_context() -> PageContext:
from urllib.parse import parse_qs, urlparse from urllib.parse import parse_qs, urlparse
referer = urlparse(request.headers.get("Referer", "")) referer = urlparse(request.headers.get("Referer", ""))
if referer.path.startswith("/_anki/pages/"): if referer.path.startswith("/_anki/pages/") or is_sveltekit_page(referer.path[1:]):
return PageContext.NON_LEGACY_PAGE return PageContext.NON_LEGACY_PAGE
elif referer.path == "/_anki/legacyPageData": elif referer.path == "/_anki/legacyPageData":
query_params = parse_qs(referer.query) query_params = parse_qs(referer.query)

View File

@ -204,7 +204,7 @@ class Overview:
) )
def _show_finished_screen(self) -> None: def _show_finished_screen(self) -> None:
self.web.load_ts_page("congrats") self.web.load_sveltekit_page("congrats")
def _desc(self, deck: dict[str, Any]) -> str: def _desc(self, deck: dict[str, Any]) -> str:
if deck["dyn"]: if deck["dyn"]:

View File

@ -134,7 +134,7 @@ class NewDeckStats(QDialog):
return False return False
def refresh(self) -> None: def refresh(self) -> None:
self.form.web.load_ts_page("graphs") self.form.web.load_sveltekit_page("graphs")
class DeckStats(QDialog): class DeckStats(QDialog):

View File

@ -14,7 +14,7 @@ import anki
import anki.lang import anki.lang
from anki._legacy import deprecated from anki._legacy import deprecated
from anki.lang import is_rtl from anki.lang import is_rtl
from anki.utils import is_lin, is_mac, is_win from anki.utils import hmr_mode, is_lin, is_mac, is_win
from aqt import colors, gui_hooks from aqt import colors, gui_hooks
from aqt.qt import * from aqt.qt import *
from aqt.theme import theme_manager from aqt.theme import theme_manager
@ -129,10 +129,13 @@ class AnkiWebPage(QWebEnginePage):
def acceptNavigationRequest( def acceptNavigationRequest(
self, url: QUrl, navType: Any, isMainFrame: bool self, url: QUrl, navType: Any, isMainFrame: bool
) -> bool: ) -> bool:
from aqt.mediasrv import is_sveltekit_page
if ( if (
not self.open_links_externally not self.open_links_externally
or "_anki/pages" in url.path() or "_anki/pages" in url.path()
or url.path() == "/_anki/legacyPageData" or url.path() == "/_anki/legacyPageData"
or is_sveltekit_page(url.path()[1:])
): ):
return super().acceptNavigationRequest(url, navType, isMainFrame) return super().acceptNavigationRequest(url, navType, isMainFrame)
@ -758,6 +761,23 @@ html {{ {font} }}
self.load_url(QUrl(f"{mw.serverURL()}_anki/pages/{name}.html{extra}")) self.load_url(QUrl(f"{mw.serverURL()}_anki/pages/{name}.html{extra}"))
self.add_dynamic_styling_and_props_then_show() self.add_dynamic_styling_and_props_then_show()
def load_sveltekit_page(self, path: str) -> None:
from aqt import mw
self.set_open_links_externally(True)
if theme_manager.night_mode:
extra = "#night"
else:
extra = ""
if hmr_mode:
server = "http://127.0.0.1:5173/"
else:
server = mw.serverURL()
self.load_url(QUrl(f"{server}{path}{extra}"))
self.add_dynamic_styling_and_props_then_show()
def force_load_hack(self) -> None: def force_load_hack(self) -> None:
"""Force process to initialize. """Force process to initialize.
Must be done on Windows prior to changing current working directory.""" Must be done on Windows prior to changing current working directory."""

View File

@ -288,9 +288,16 @@ fn get_modules(langs: &[LanguageIdentifier], desired_modules: &[String]) -> Vec<
let mut buf = String::new(); let mut buf = String::new();
let lang_name = remapped_lang_name(&lang); let lang_name = remapped_lang_name(&lang);
if let Some(strings) = STRINGS.get(lang_name) { if let Some(strings) = STRINGS.get(lang_name) {
for module_name in desired_modules { if desired_modules.is_empty() {
if let Some(text) = strings.get(module_name.as_str()) { // empty list, provide all modules
buf.push_str(text); for value in strings.values() {
buf.push_str(value)
}
} else {
for module_name in desired_modules {
if let Some(text) = strings.get(module_name.as_str()) {
buf.push_str(text);
}
} }
} }
} }

View File

@ -16,41 +16,32 @@ use crate::extract::Variable;
use crate::extract::VariableKind; use crate::extract::VariableKind;
pub fn write_ts_interface(modules: &[Module]) -> Result<()> { pub fn write_ts_interface(modules: &[Module]) -> Result<()> {
let mut dts_out = header(); let mut ts_out = header();
let mut js_out = header(); write_imports(&mut ts_out);
write_translate_method(&mut js_out);
dts_out.push_str("export declare const funcs: any;\n");
render_module_map(modules, &mut dts_out, &mut js_out); render_module_map(modules, &mut ts_out);
render_methods(modules, &mut dts_out, &mut js_out); render_methods(modules, &mut ts_out);
if let Ok(path) = env::var("STRINGS_JS") { if let Ok(path) = env::var("STRINGS_TS") {
let path = PathBuf::from(path); let path = PathBuf::from(path);
create_dir_all(path.parent().unwrap())?; create_dir_all(path.parent().unwrap())?;
write_file_if_changed(path, js_out)?; write_file_if_changed(path, ts_out)?;
}
if let Ok(path) = env::var("STRINGS_DTS") {
let path = PathBuf::from(path);
create_dir_all(path.parent().unwrap())?;
write_file_if_changed(path, dts_out)?;
} }
Ok(()) Ok(())
} }
fn render_module_map(modules: &[Module], dts_out: &mut String, js_out: &mut String) { fn render_module_map(modules: &[Module], ts_out: &mut String) {
dts_out.push_str("export declare enum ModuleName {\n"); ts_out.push_str("export enum ModuleName {\n");
js_out.push_str("export const ModuleName = {};\n");
for module in modules { for module in modules {
let name = &module.name; let name = &module.name;
let upper = name.to_upper_case(); let upper = name.to_upper_case();
writeln!(dts_out, r#" {upper} = "{name}","#).unwrap(); writeln!(ts_out, r#" {upper} = "{name}","#).unwrap();
writeln!(js_out, r#"ModuleName["{upper}"] = "{name}";"#).unwrap();
} }
dts_out.push('}'); ts_out.push('}');
} }
fn render_methods(modules: &[Module], dts_out: &mut String, js_out: &mut String) { fn render_methods(modules: &[Module], ts_out: &mut String) {
for module in modules { for module in modules {
for translation in &module.translations { for translation in &module.translations {
let text = &translation.text; let text = &translation.text;
@ -59,20 +50,14 @@ fn render_methods(modules: &[Module], dts_out: &mut String, js_out: &mut String)
let arg_types = get_arg_types(&translation.variables); let arg_types = get_arg_types(&translation.variables);
let args = get_args(&translation.variables); let args = get_args(&translation.variables);
let maybe_args = if translation.variables.is_empty() { let maybe_args = if translation.variables.is_empty() {
"" "".to_string()
} else { } else {
"args" arg_types
}; };
writeln!( writeln!(
dts_out, ts_out,
"
/** {text} */
export declare function {func_name}({arg_types}): string;",
)
.unwrap();
writeln!(
js_out,
r#" r#"
/** {text} */
export function {func_name}({maybe_args}) {{ export function {func_name}({maybe_args}) {{
return translate("{key}", {args}) return translate("{key}", {args})
}}"#, }}"#,
@ -101,23 +86,15 @@ fn get_args(variables: &[Variable]) -> String {
} }
fn typescript_arg_name(name: &str) -> String { fn typescript_arg_name(name: &str) -> String {
let name = name.replace('-', "_").to_camel_case(); name.replace('-', "_").to_camel_case()
if name == "new" {
"new_".into()
} else {
name
}
} }
fn write_translate_method(buf: &mut String) { fn write_imports(buf: &mut String) {
buf.push_str( buf.push_str(
" "
// tslib is responsible for injecting getMessage helper in import { translate } from './ftl-helpers';
export const funcs = {}; export { firstLanguage, setBundles } from './ftl-helpers';
export { FluentBundle, FluentResource } from '@fluent/bundle';
function translate(key, args = {}) {
return funcs.getMessage(key, args) ?? `missing key: ${key}`;
}
", ",
); );
} }

View File

@ -74,7 +74,7 @@ fn ts_help_pages() -> impl Iterator<Item = &'static str> {
static ref QUOTED_URL: Regex = Regex::new("\"(http.+)\"").unwrap(); static ref QUOTED_URL: Regex = Regex::new("\"(http.+)\"").unwrap();
} }
QUOTED_URL QUOTED_URL
.captures_iter(include_str!("../../../ts/lib/help-page.ts")) .captures_iter(include_str!("../../../ts/lib/tslib/help-page.ts"))
.map(|caps| caps.get(1).unwrap().as_str()) .map(|caps| caps.get(1).unwrap().as_str())
} }

View File

@ -14,11 +14,10 @@ use inflections::Inflect;
use itertools::Itertools; use itertools::Itertools;
pub(crate) fn write_ts_interface(services: &[BackendService]) -> Result<()> { pub(crate) fn write_ts_interface(services: &[BackendService]) -> Result<()> {
let root = Path::new("../../out/ts/lib"); let root = Path::new("../../out/ts/lib/generated");
create_dir_all(root)?; create_dir_all(root)?;
let mut dts_out = String::new(); let mut ts_out = String::new();
let mut js_out = String::new();
let mut referenced_packages = HashSet::new(); let mut referenced_packages = HashSet::new();
for service in services { for service in services {
@ -30,30 +29,26 @@ pub(crate) fn write_ts_interface(services: &[BackendService]) -> Result<()> {
let method = MethodDetails::from_method(method); let method = MethodDetails::from_method(method);
record_referenced_type(&mut referenced_packages, &method.input_type); record_referenced_type(&mut referenced_packages, &method.input_type);
record_referenced_type(&mut referenced_packages, &method.output_type); record_referenced_type(&mut referenced_packages, &method.output_type);
write_dts_method(&method, &mut dts_out); write_ts_method(&method, &mut ts_out);
write_js_method(&method, &mut js_out);
} }
} }
let imports = imports(referenced_packages); let imports = imports(referenced_packages);
write_file_if_changed( write_file_if_changed(
root.join("backend.d.ts"), root.join("backend.ts"),
format!("{}{}{}", dts_header(), imports, dts_out), format!("{}{}{}", ts_header(), imports, ts_out),
)?;
write_file_if_changed(
root.join("backend.js"),
format!("{}{}{}", js_header(), imports, js_out),
)?; )?;
Ok(()) Ok(())
} }
fn dts_header() -> String { fn ts_header() -> String {
r#"// Copyright: Ankitects Pty Ltd and contributors r#"// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; https://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; https://www.gnu.org/licenses/agpl.html
import type { PlainMessage } from "@bufbuild/protobuf"; import type { PlainMessage } from "@bufbuild/protobuf";
import type { PostProtoOptions } from "./post"; import type { PostProtoOptions } from "./post";
import { postProto } from "./post";
"# "#
.into() .into()
} }
@ -72,7 +67,7 @@ fn imports(referenced_packages: HashSet<String>) -> String {
out out
} }
fn write_dts_method( fn write_ts_method(
MethodDetails { MethodDetails {
method_name, method_name,
input_type, input_type,
@ -84,38 +79,12 @@ fn write_dts_method(
let comments = format_comments(comments); let comments = format_comments(comments);
writeln!( writeln!(
out, out,
r#"{comments}export declare function {method_name}(input: PlainMessage<{input_type}>, options?: PostProtoOptions): Promise<{output_type}>;"# r#"{comments}export async function {method_name}(input: PlainMessage<{input_type}>, options?: PostProtoOptions): Promise<{output_type}> {{
return await postProto("{method_name}", new {input_type}(input), {output_type}, options);
}}"#
).unwrap() ).unwrap()
} }
fn js_header() -> String {
r#"// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; https://www.gnu.org/licenses/agpl.html
import { postProto } from "./post";
"#
.into()
}
fn write_js_method(
MethodDetails {
method_name,
input_type,
output_type,
..
}: &MethodDetails,
out: &mut String,
) {
write!(
out,
r#"export async function {method_name}(input, options = {{}}) {{
return await postProto("{method_name}", new {input_type}(input), {output_type}, options);
}}
"#
)
.unwrap();
}
fn format_comments(comments: &Option<String>) -> String { fn format_comments(comments: &Option<String>) -> String {
comments comments
.as_ref() .as_ref()

View File

@ -42,6 +42,7 @@ const IGNORED_FOLDERS: &[&str] = &[
"./target", "./target",
".mypy_cache", ".mypy_cache",
"./extra", "./extra",
"./ts/.svelte-kit",
]; ];
fn main() -> Result<()> { fn main() -> Result<()> {
@ -90,7 +91,7 @@ impl LintContext {
.into_iter() .into_iter()
.map(Some) .map(Some)
.collect(); .collect();
if exts.contains(&path.extension()) { if exts.contains(&path.extension()) && !sveltekit_temp_file(path.as_str()) {
self.check_copyright(path)?; self.check_copyright(path)?;
self.check_triple_slash(path)?; self.check_triple_slash(path)?;
} }
@ -202,6 +203,11 @@ impl LintContext {
} }
} }
/// Annoyingly, sveltekit writes temp files into ts/ folder when it's running.
fn sveltekit_temp_file(path: &str) -> bool {
path.contains("vite.config.ts.timestamp")
}
fn check_cargo_deny() -> Result<()> { fn check_cargo_deny() -> Result<()> {
Command::run("cargo install cargo-deny@0.14.12")?; Command::run("cargo install cargo-deny@0.14.12")?;
Command::run("cargo deny check")?; Command::run("cargo deny check")?;

View File

@ -31,7 +31,7 @@ if (!sourcemap) {
define: { define: {
"process.browser": "true", "process.browser": "true",
}, },
tsconfig: "ts/tsconfig.json", tsconfig: "ts/tsconfig_legacy.json",
}), }),
sveltePreprocess({ typescript: false }), sveltePreprocess({ typescript: false }),
]; ];
@ -52,7 +52,7 @@ build({
preserveSymlinks: true, preserveSymlinks: true,
sourcemap: sourcemap ? "inline" : false, sourcemap: sourcemap ? "inline" : false,
plugins: [ plugins: [
sassPlugin({ loadPaths: [".", "node_modules"] }), sassPlugin({ loadPaths: ["node_modules"] }),
sveltePlugin({ sveltePlugin({
compilerOptions: { css: inlineCss ? "injected" : "external" }, compilerOptions: { css: inlineCss ? "injected" : "external" },
preprocess: sveltePlugins, preprocess: sveltePlugins,

View File

@ -1,59 +0,0 @@
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import type {
CardStatsResponse,
CardStatsResponse_StatsRevlogEntry,
} from "@tslib/anki/stats_pb";
import { cardStats } from "@tslib/backend";
import Container from "../components/Container.svelte";
import Row from "../components/Row.svelte";
import CardInfoPlaceholder from "./CardInfoPlaceholder.svelte";
import CardStats from "./CardStats.svelte";
import Revlog from "./Revlog.svelte";
export let includeRevlog: boolean = true;
let stats: CardStatsResponse | null = null;
let revlog: CardStatsResponse_StatsRevlogEntry[] | null = null;
export async function updateStats(cardId: bigint | null): Promise<void> {
const requestedCardId = cardId;
if (cardId === null) {
stats = null;
revlog = null;
return;
}
const updatedStats = await cardStats({ cid: cardId });
/* Skip if another update has been triggered in the meantime. */
if (requestedCardId === cardId) {
stats = updatedStats;
if (includeRevlog) {
revlog = stats.revlog;
}
}
}
</script>
<Container breakpoint="md" --gutter-inline="1rem" --gutter-block="0.5rem">
{#if stats}
<Row>
<CardStats {stats} />
</Row>
{#if revlog}
<Row>
<Revlog {revlog} />
</Row>
{/if}
{:else}
<CardInfoPlaceholder />
{/if}
</Container>

View File

@ -1 +0,0 @@
@import "sass/base";

View File

@ -1,5 +0,0 @@
{
"extends": "../tsconfig.json",
"include": ["*"],
"references": [{ "path": "../lib" }]
}

View File

@ -1,10 +0,0 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
/// <reference types="../lib/image-import" />
export { default as arrowLeftIcon } from "bootstrap-icons/icons/arrow-left.svg";
export { default as arrowRightIcon } from "bootstrap-icons/icons/arrow-right.svg";
export { default as minusIcon } from "bootstrap-icons/icons/dash-lg.svg";
export { default as exclamationIcon } from "bootstrap-icons/icons/exclamation-circle.svg";
export { default as plusIcon } from "bootstrap-icons/icons/plus-lg.svg";

View File

@ -1,12 +0,0 @@
{
"extends": "../tsconfig.json",
"include": ["*"],
"references": [
{ "path": "../lib" },
{ "path": "../sveltelib" },
{ "path": "../components" }
],
"compilerOptions": {
"types": ["jest"]
}
}

View File

@ -1,15 +0,0 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
/// <reference types="../lib/image-import" />
export { default as hsplitIcon } from "@mdi/svg/svg/arrow-split-horizontal.svg";
export { default as vsplitIcon } from "@mdi/svg/svg/arrow-split-vertical.svg";
export { default as chevronDown } from "@mdi/svg/svg/chevron-down.svg";
export { default as chevronLeft } from "@mdi/svg/svg/chevron-left.svg";
export { default as chevronRight } from "@mdi/svg/svg/chevron-right.svg";
export { default as chevronUp } from "@mdi/svg/svg/chevron-up.svg";
export { default as horizontalHandle } from "@mdi/svg/svg/drag-horizontal.svg";
export { default as verticalHandle } from "@mdi/svg/svg/drag-vertical.svg";
export { default as infoCircle } from "@mdi/svg/svg/help-circle.svg";
export { default as revertIcon } from "bootstrap-icons/icons/arrow-counterclockwise.svg";

View File

@ -1,5 +0,0 @@
{
"extends": "../tsconfig.json",
"include": ["*"],
"references": [{ "path": "../lib" }, { "path": "../sveltelib" }]
}

View File

@ -1,8 +0,0 @@
{
"extends": "../tsconfig.json",
"include": ["*"],
"references": [{ "path": "../lib" }],
"compilerOptions": {
"types": ["node"]
}
}

View File

@ -1,7 +0,0 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
/// <reference types="../lib/image-import" />
export { default as chevronDown } from "@mdi/svg/svg/chevron-down.svg";
export { default as gearIcon } from "bootstrap-icons/icons/gear.svg";

View File

@ -1,12 +0,0 @@
{
"extends": "../tsconfig.json",
"include": ["*"],
"references": [
{ "path": "@tslib" },
{ "path": "../sveltelib" },
{ "path": "../components" }
],
"compilerOptions": {
"types": ["jest"]
}
}

View File

@ -1,15 +0,0 @@
{
"extends": "../tsconfig.json",
"include": [
"*",
"location/*",
"surround/*",
"surround/apply/*",
"surround/build/*",
"surround/tree/*"
],
"references": [{ "path": "../lib" }],
"compilerOptions": {
"types": ["jest"]
}
}

View File

@ -9,10 +9,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<script lang="ts"> <script lang="ts">
import type { Writable } from "svelte/store"; import type { Writable } from "svelte/store";
import { updateAllState } from "../components/WithState.svelte"; import { updateAllState } from "$lib/components/WithState.svelte";
import actionList from "../sveltelib/action-list"; import actionList from "$lib/sveltelib/action-list";
import type { MirrorAction } from "../sveltelib/dom-mirror"; import type { MirrorAction } from "$lib/sveltelib/dom-mirror";
import type { SetupInputHandlerAction } from "../sveltelib/input-handler"; import type { SetupInputHandlerAction } from "$lib/sveltelib/input-handler";
import type { ContentEditableAPI } from "./content-editable"; import type { ContentEditableAPI } from "./content-editable";
import { import {
fixRTLKeyboardNav, fixRTLKeyboardNav,

View File

@ -22,7 +22,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { onDestroy } from "svelte"; import { onDestroy } from "svelte";
import { writable } from "svelte/store"; import { writable } from "svelte/store";
import { pageTheme } from "../sveltelib/theme"; import { pageTheme } from "$lib/sveltelib/theme";
import { convertMathjax, unescapeSomeEntities } from "./mathjax"; import { convertMathjax, unescapeSomeEntities } from "./mathjax";
export let mathjax: string; export let mathjax: string;

View File

@ -8,10 +8,10 @@ import { isApplePlatform } from "@tslib/platform";
import { registerShortcut } from "@tslib/shortcuts"; import { registerShortcut } from "@tslib/shortcuts";
import type { Callback } from "@tslib/typing"; import type { Callback } from "@tslib/typing";
import type { SelectionLocation } from "../domlib/location"; import type { SelectionLocation } from "$lib/domlib/location";
import { restoreSelection, saveSelection } from "../domlib/location"; import { restoreSelection, saveSelection } from "$lib/domlib/location";
import { placeCaretAfterContent } from "../domlib/place-caret"; import { placeCaretAfterContent } from "$lib/domlib/place-caret";
import { HandlerList } from "../sveltelib/handler-list"; import { HandlerList } from "$lib/sveltelib/handler-list";
/** /**
* Workaround: If you try to invoke an IME after calling * Workaround: If you try to invoke an IME after calling

View File

@ -1,4 +1,4 @@
@use "sass/scrollbar"; @use "../lib/sass/scrollbar";
* { * {
max-width: 100%; max-width: 100%;

View File

@ -5,8 +5,9 @@ import { getSelection, isSelectionCollapsed } from "@tslib/cross-browser";
import { elementIsBlock, hasBlockAttribute, nodeIsElement, nodeIsText } from "@tslib/dom"; import { elementIsBlock, hasBlockAttribute, nodeIsElement, nodeIsText } from "@tslib/dom";
import { on } from "@tslib/events"; import { on } from "@tslib/events";
import { moveChildOutOfElement } from "../domlib/move-nodes"; import { moveChildOutOfElement } from "$lib/domlib/move-nodes";
import { placeCaretAfter, placeCaretBefore } from "../domlib/place-caret"; import { placeCaretAfter, placeCaretBefore } from "$lib/domlib/place-caret";
import type { FrameHandle } from "./frame-handle"; import type { FrameHandle } from "./frame-handle";
import { checkHandles, frameElementTagName, FrameEnd, FrameStart, isFrameHandle } from "./frame-handle"; import { checkHandles, frameElementTagName, FrameEnd, FrameStart, isFrameHandle } from "./frame-handle";

View File

@ -7,9 +7,10 @@ import { on } from "@tslib/events";
import type { Unsubscriber } from "svelte/store"; import type { Unsubscriber } from "svelte/store";
import { get } from "svelte/store"; import { get } from "svelte/store";
import { moveChildOutOfElement } from "../domlib/move-nodes"; import { moveChildOutOfElement } from "$lib/domlib/move-nodes";
import { placeCaretAfter } from "../domlib/place-caret"; import { placeCaretAfter } from "$lib/domlib/place-caret";
import { isComposing } from "../sveltelib/composition"; import { isComposing } from "$lib/sveltelib/composition";
import type { FrameElement } from "./frame-element"; import type { FrameElement } from "./frame-element";
/** /**

View File

@ -1,6 +1,4 @@
// Copyright: Ankitects Pty Ltd and contributors // Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
/// <reference types="../lib/image-import" />
export { default as mathIcon } from "@mdi/svg/svg/math-integral-box.svg"; export { default as mathIcon } from "@mdi/svg/svg/math-integral-box.svg";

View File

@ -3,7 +3,8 @@
import { on } from "@tslib/events"; import { on } from "@tslib/events";
import { placeCaretAfter, placeCaretBefore } from "../domlib/place-caret"; import { placeCaretAfter, placeCaretBefore } from "$lib/domlib/place-caret";
import type { DecoratedElement, DecoratedElementConstructor } from "./decorated"; import type { DecoratedElement, DecoratedElementConstructor } from "./decorated";
import { FrameElement, frameElement } from "./frame-element"; import { FrameElement, frameElement } from "./frame-element";
import Mathjax_svelte from "./Mathjax.svelte"; import Mathjax_svelte from "./Mathjax.svelte";

View File

@ -1,11 +0,0 @@
{
"extends": "../tsconfig.json",
"include": ["*"],
"references": [
{ "path": "../components" },
{ "path": "../lib" },
{ "path": "../domlib" },
{ "path": "../sveltelib" },
{ "path": "../mathjax" }
]
}

View File

@ -3,7 +3,8 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import ButtonGroupItem from "../components/ButtonGroupItem.svelte"; import ButtonGroupItem from "$lib/components/ButtonGroupItem.svelte";
import type { NoteEditorAPI } from "./NoteEditor.svelte"; import type { NoteEditorAPI } from "./NoteEditor.svelte";
import NoteEditor from "./NoteEditor.svelte"; import NoteEditor from "./NoteEditor.svelte";
import PreviewButton from "./PreviewButton.svelte"; import PreviewButton from "./PreviewButton.svelte";

View File

@ -3,15 +3,16 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@tslib/ftl"; import * as tr from "@generated/ftl";
import { isApplePlatform } from "@tslib/platform"; import { isApplePlatform } from "@tslib/platform";
import { getPlatformString } from "@tslib/shortcuts"; import { getPlatformString } from "@tslib/shortcuts";
import { createEventDispatcher } from "svelte"; import { createEventDispatcher } from "svelte";
import { get } from "svelte/store"; import { get } from "svelte/store";
import ButtonGroup from "../components/ButtonGroup.svelte"; import ButtonGroup from "$lib/components/ButtonGroup.svelte";
import IconButton from "../components/IconButton.svelte"; import IconButton from "$lib/components/IconButton.svelte";
import Shortcut from "../components/Shortcut.svelte"; import Shortcut from "$lib/components/Shortcut.svelte";
import { clozeIcon, incrementClozeIcon } from "./icons"; import { clozeIcon, incrementClozeIcon } from "./icons";
import { context as noteEditorContext } from "./NoteEditor.svelte"; import { context as noteEditorContext } from "./NoteEditor.svelte";
import { editingInputIsRichText } from "./rich-text-input"; import { editingInputIsRichText } from "./rich-text-input";

View File

@ -20,7 +20,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { createEventDispatcher, getContext, onMount } from "svelte"; import { createEventDispatcher, getContext, onMount } from "svelte";
import type { Writable } from "svelte/store"; import type { Writable } from "svelte/store";
import { pageTheme } from "../sveltelib/theme"; import { pageTheme } from "$lib/sveltelib/theme";
import { import {
darkTheme, darkTheme,
lightTheme, lightTheme,

View File

@ -3,7 +3,8 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import Badge from "../components/Badge.svelte"; import Badge from "$lib/components/Badge.svelte";
import { chevronDown } from "./icons"; import { chevronDown } from "./icons";
export let collapsed = false; export let collapsed = false;

View File

@ -3,8 +3,8 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@generated/ftl";
import { bridgeCommand } from "@tslib/bridgecommand"; import { bridgeCommand } from "@tslib/bridgecommand";
import * as tr from "@tslib/ftl";
</script> </script>
<span class="duplicate-link-container"> <span class="duplicate-link-container">

View File

@ -5,7 +5,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<script context="module" lang="ts"> <script context="module" lang="ts">
import type { Writable } from "svelte/store"; import type { Writable } from "svelte/store";
import contextProperty from "../sveltelib/context-property"; import contextProperty from "$lib/sveltelib/context-property";
export interface FocusableInputAPI { export interface FocusableInputAPI {
readonly name: string; readonly name: string;

View File

@ -26,8 +26,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { registerPackage } from "@tslib/runtime-require"; import { registerPackage } from "@tslib/runtime-require";
import contextProperty from "../sveltelib/context-property"; import contextProperty from "$lib/sveltelib/context-property";
import lifecycleHooks from "../sveltelib/lifecycle-hooks"; import lifecycleHooks from "$lib/sveltelib/lifecycle-hooks";
const key = Symbol("editorField"); const key = Symbol("editorField");
const [context, setContextProperty] = contextProperty<EditorFieldAPI>(key); const [context, setContextProperty] = contextProperty<EditorFieldAPI>(key);
@ -50,7 +50,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import type { Writable } from "svelte/store"; import type { Writable } from "svelte/store";
import { writable } from "svelte/store"; import { writable } from "svelte/store";
import Collapsible from "../components/Collapsible.svelte"; import Collapsible from "$lib/components/Collapsible.svelte";
import type { Destroyable } from "./destroyable"; import type { Destroyable } from "./destroyable";
import EditingArea from "./EditingArea.svelte"; import EditingArea from "./EditingArea.svelte";
@ -119,7 +120,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</div> </div>
<style lang="scss"> <style lang="scss">
@use "sass/elevation" as *; @use "../lib/sass/elevation" as *;
/* Make sure labels are readable on custom Qt backgrounds */ /* Make sure labels are readable on custom Qt backgrounds */
.field-container { .field-container {

View File

@ -3,7 +3,7 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import ScrollArea from "components/ScrollArea.svelte"; import ScrollArea from "$lib/components/ScrollArea.svelte";
</script> </script>
<!-- <!--

View File

@ -5,7 +5,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<script lang="ts"> <script lang="ts">
import { createEventDispatcher } from "svelte"; import { createEventDispatcher } from "svelte";
import { pageTheme } from "../sveltelib/theme"; import { pageTheme } from "$lib/sveltelib/theme";
export let offsetX = 0; export let offsetX = 0;
export let offsetY = 0; export let offsetY = 0;

View File

@ -3,7 +3,7 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@tslib/ftl"; import * as tr from "@generated/ftl";
import CollapseLabel from "./CollapseLabel.svelte"; import CollapseLabel from "./CollapseLabel.svelte";

View File

@ -5,7 +5,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<script context="module" lang="ts"> <script context="module" lang="ts">
import type { Writable } from "svelte/store"; import type { Writable } from "svelte/store";
import Collapsible from "../components/Collapsible.svelte"; import Collapsible from "$lib/components/Collapsible.svelte";
import type { EditingInputAPI } from "./EditingArea.svelte"; import type { EditingInputAPI } from "./EditingArea.svelte";
import type { EditorToolbarAPI } from "./editor-toolbar"; import type { EditorToolbarAPI } from "./editor-toolbar";
import type { EditorFieldAPI } from "./EditorField.svelte"; import type { EditorFieldAPI } from "./EditorField.svelte";
@ -23,8 +24,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { registerPackage } from "@tslib/runtime-require"; import { registerPackage } from "@tslib/runtime-require";
import contextProperty from "../sveltelib/context-property"; import contextProperty from "$lib/sveltelib/context-property";
import lifecycleHooks from "../sveltelib/lifecycle-hooks"; import lifecycleHooks from "$lib/sveltelib/lifecycle-hooks";
const key = Symbol("noteEditor"); const key = Symbol("noteEditor");
const [context, setContextProperty] = contextProperty<NoteEditorAPI>(key); const [context, setContextProperty] = contextProperty<NoteEditorAPI>(key);
@ -40,16 +41,20 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script> </script>
<script lang="ts"> <script lang="ts">
import * as tr from "@generated/ftl";
import { bridgeCommand } from "@tslib/bridgecommand"; import { bridgeCommand } from "@tslib/bridgecommand";
import * as tr from "@tslib/ftl";
import { type ImageLoadedEvent, resetIOImage } from "image-occlusion/mask-editor";
import { onMount, tick } from "svelte"; import { onMount, tick } from "svelte";
import { get, writable } from "svelte/store"; import { get, writable } from "svelte/store";
import Absolute from "../components/Absolute.svelte"; import Absolute from "$lib/components/Absolute.svelte";
import Badge from "../components/Badge.svelte"; import Badge from "$lib/components/Badge.svelte";
import { TagEditor } from "../tag-editor"; import { TagEditor } from "$lib/tag-editor";
import { commitTagEdits } from "../tag-editor/TagInput.svelte"; import { commitTagEdits } from "$lib/tag-editor/TagInput.svelte";
import {
type ImageLoadedEvent,
resetIOImage,
} from "../routes/image-occlusion/mask-editor";
import { ChangeTimer } from "./change-timer"; import { ChangeTimer } from "./change-timer";
import { clearableArray } from "./destroyable"; import { clearableArray } from "./destroyable";
import DuplicateLink from "./DuplicateLink.svelte"; import DuplicateLink from "./DuplicateLink.svelte";
@ -385,21 +390,22 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
}); });
} }
import { ImageOcclusionFieldIndexes } from "@tslib/anki/image_occlusion_pb"; import { ImageOcclusionFieldIndexes } from "@generated/anki/image_occlusion_pb";
import { getImageOcclusionFields } from "@tslib/backend"; import { getImageOcclusionFields } from "@generated/backend";
import { wrapInternal } from "@tslib/wrap"; import { wrapInternal } from "@tslib/wrap";
import Shortcut from "components/Shortcut.svelte";
import ImageOcclusionPage from "image-occlusion/ImageOcclusionPage.svelte"; import Shortcut from "$lib/components/Shortcut.svelte";
import ImageOcclusionPicker from "image-occlusion/ImageOcclusionPicker.svelte";
import type { IOMode } from "image-occlusion/lib"; import { mathjaxConfig } from "../editable/mathjax-element";
import { exportShapesToClozeDeletions } from "image-occlusion/shapes/to-cloze"; import ImageOcclusionPage from "../routes/image-occlusion/ImageOcclusionPage.svelte";
import ImageOcclusionPicker from "../routes/image-occlusion/ImageOcclusionPicker.svelte";
import type { IOMode } from "../routes/image-occlusion/lib";
import { exportShapesToClozeDeletions } from "../routes/image-occlusion/shapes/to-cloze";
import { import {
hideAllGuessOne, hideAllGuessOne,
ioImageLoadedStore, ioImageLoadedStore,
ioMaskEditorVisible, ioMaskEditorVisible,
} from "image-occlusion/store"; } from "../routes/image-occlusion/store";
import { mathjaxConfig } from "../editable/mathjax-element";
import CollapseLabel from "./CollapseLabel.svelte"; import CollapseLabel from "./CollapseLabel.svelte";
import * as oldEditorAdapter from "./old-editor-adapter"; import * as oldEditorAdapter from "./old-editor-adapter";

View File

@ -3,11 +3,12 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@tslib/ftl"; import * as tr from "@generated/ftl";
import { getPlatformString, registerShortcut } from "@tslib/shortcuts"; import { getPlatformString, registerShortcut } from "@tslib/shortcuts";
import { createEventDispatcher, onDestroy } from "svelte"; import { createEventDispatcher, onDestroy } from "svelte";
import Badge from "../components/Badge.svelte"; import Badge from "$lib/components/Badge.svelte";
import { context as editorFieldContext } from "./EditorField.svelte"; import { context as editorFieldContext } from "./EditorField.svelte";
import { plainTextIcon } from "./icons"; import { plainTextIcon } from "./icons";

View File

@ -15,12 +15,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script> </script>
<script lang="ts"> <script lang="ts">
import * as tr from "@generated/ftl";
import { bridgeCommand } from "@tslib/bridgecommand"; import { bridgeCommand } from "@tslib/bridgecommand";
import * as tr from "@tslib/ftl";
import { getPlatformString } from "@tslib/shortcuts"; import { getPlatformString } from "@tslib/shortcuts";
import LabelButton from "../components/LabelButton.svelte"; import LabelButton from "$lib/components/LabelButton.svelte";
import Shortcut from "../components/Shortcut.svelte"; import Shortcut from "$lib/components/Shortcut.svelte";
const keyCombination = "Control+Shift+P"; const keyCombination = "Control+Shift+P";
function preview(): void { function preview(): void {

View File

@ -3,11 +3,12 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@tslib/ftl"; import * as tr from "@generated/ftl";
import { getPlatformString, registerShortcut } from "@tslib/shortcuts"; import { getPlatformString, registerShortcut } from "@tslib/shortcuts";
import { createEventDispatcher, onDestroy } from "svelte"; import { createEventDispatcher, onDestroy } from "svelte";
import Badge from "../components/Badge.svelte"; import Badge from "$lib/components/Badge.svelte";
import { context as editorFieldContext } from "./EditorField.svelte"; import { context as editorFieldContext } from "./EditorField.svelte";
import { richTextIcon } from "./icons"; import { richTextIcon } from "./icons";

View File

@ -3,12 +3,13 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@generated/ftl";
import { bridgeCommand } from "@tslib/bridgecommand"; import { bridgeCommand } from "@tslib/bridgecommand";
import * as tr from "@tslib/ftl";
import { getPlatformString, registerShortcut } from "@tslib/shortcuts"; import { getPlatformString, registerShortcut } from "@tslib/shortcuts";
import { onMount } from "svelte"; import { onMount } from "svelte";
import Badge from "../components/Badge.svelte"; import Badge from "$lib/components/Badge.svelte";
import { context as editorFieldContext } from "./EditorField.svelte"; import { context as editorFieldContext } from "./EditorField.svelte";
import { stickyIcon } from "./icons"; import { stickyIcon } from "./icons";

View File

@ -8,16 +8,17 @@
import "./legacy.scss"; import "./legacy.scss";
import "./editor-base.scss"; import "./editor-base.scss";
import "@tslib/runtime-require"; import "@tslib/runtime-require";
import "../sveltelib/export-runtime"; import "$lib/sveltelib/export-runtime";
import { setupI18n } from "@tslib/i18n"; import { setupI18n } from "@tslib/i18n";
import { uiResolve } from "@tslib/ui"; import { uiResolve } from "@tslib/ui";
import * as contextKeys from "../components/context-keys"; import * as contextKeys from "$lib/components/context-keys";
import IconButton from "../components/IconButton.svelte"; import IconButton from "$lib/components/IconButton.svelte";
import LabelButton from "../components/LabelButton.svelte"; import LabelButton from "$lib/components/LabelButton.svelte";
import WithContext from "../components/WithContext.svelte"; import WithContext from "$lib/components/WithContext.svelte";
import WithState from "../components/WithState.svelte"; import WithState from "$lib/components/WithState.svelte";
import BrowserEditor from "./BrowserEditor.svelte"; import BrowserEditor from "./BrowserEditor.svelte";
import NoteCreator from "./NoteCreator.svelte"; import NoteCreator from "./NoteCreator.svelte";
import * as editorContextKeys from "./NoteEditor.svelte"; import * as editorContextKeys from "./NoteEditor.svelte";

View File

@ -12,7 +12,7 @@ export class ChangeTimer {
schedule(action: () => void, delay: number): void { schedule(action: () => void, delay: number): void {
this.clear(); this.clear();
this.action = action; this.action = action;
this.value = setTimeout(this.fireImmediately, delay); this.value = setTimeout(this.fireImmediately, delay) as any;
} }
clear(): void { clear(): void {

View File

@ -16,7 +16,7 @@ import "codemirror/addon/display/placeholder";
import CodeMirror from "codemirror"; import CodeMirror from "codemirror";
import type { Readable } from "svelte/store"; import type { Readable } from "svelte/store";
import storeSubscribe from "../sveltelib/store-subscribe"; import storeSubscribe from "$lib/sveltelib/store-subscribe";
export { CodeMirror }; export { CodeMirror };

View File

@ -1,12 +1,12 @@
/* Copyright: Ankitects Pty Ltd and contributors /* Copyright: Ankitects Pty Ltd and contributors
* License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */ * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */
@import "sass/base"; @import "../lib/sass/base";
$btn-disabled-opacity: 0.4; $btn-disabled-opacity: 0.4;
@import "bootstrap/scss/buttons"; @import "bootstrap/scss/buttons";
@import "bootstrap/scss/button-group"; @import "bootstrap/scss/button-group";
@import "sass/bootstrap-tooltip"; @import "../lib/sass/bootstrap-tooltip";
html, html,
body { body {

View File

@ -3,7 +3,7 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import ButtonGroup from "../../components/ButtonGroup.svelte"; import ButtonGroup from "$lib/components/ButtonGroup.svelte";
export let buttons: string[]; export let buttons: string[];

View File

@ -3,24 +3,25 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@generated/ftl";
import { getListItem } from "@tslib/dom"; import { getListItem } from "@tslib/dom";
import { preventDefault } from "@tslib/events"; import { preventDefault } from "@tslib/events";
import * as tr from "@tslib/ftl";
import { getPlatformString, registerShortcut } from "@tslib/shortcuts"; import { getPlatformString, registerShortcut } from "@tslib/shortcuts";
import { onMount } from "svelte"; import { onMount } from "svelte";
import ButtonGroup from "../../components/ButtonGroup.svelte"; import ButtonGroup from "$lib/components/ButtonGroup.svelte";
import ButtonGroupItem, { import ButtonGroupItem, {
createProps, createProps,
setSlotHostContext, setSlotHostContext,
updatePropsList, updatePropsList,
} from "../../components/ButtonGroupItem.svelte"; } from "$lib/components/ButtonGroupItem.svelte";
import ButtonToolbar from "../../components/ButtonToolbar.svelte"; import ButtonToolbar from "$lib/components/ButtonToolbar.svelte";
import DynamicallySlottable from "../../components/DynamicallySlottable.svelte"; import DynamicallySlottable from "$lib/components/DynamicallySlottable.svelte";
import IconButton from "../../components/IconButton.svelte"; import IconButton from "$lib/components/IconButton.svelte";
import Popover from "../../components/Popover.svelte"; import Popover from "$lib/components/Popover.svelte";
import WithFloating from "../../components/WithFloating.svelte"; import WithFloating from "$lib/components/WithFloating.svelte";
import { execCommand } from "../../domlib"; import { execCommand } from "$lib/domlib";
import { context } from "../NoteEditor.svelte"; import { context } from "../NoteEditor.svelte";
import { editingInputIsRichText } from "../rich-text-input"; import { editingInputIsRichText } from "../rich-text-input";
import CommandIconButton from "./CommandIconButton.svelte"; import CommandIconButton from "./CommandIconButton.svelte";

View File

@ -3,10 +3,11 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@tslib/ftl"; import * as tr from "@generated/ftl";
import { removeStyleProperties } from "@tslib/styling"; import { removeStyleProperties } from "@tslib/styling";
import type { MatchType } from "../../domlib/surround"; import type { MatchType } from "$lib/domlib/surround";
import { boldIcon } from "./icons"; import { boldIcon } from "./icons";
import TextAttributeButton from "./TextAttributeButton.svelte"; import TextAttributeButton from "./TextAttributeButton.svelte";

View File

@ -3,7 +3,7 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import Shortcut from "../../components/Shortcut.svelte"; import Shortcut from "$lib/components/Shortcut.svelte";
export let keyCombination: string | null = null; export let keyCombination: string | null = null;
export let value: string; export let value: string;

View File

@ -5,11 +5,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<script lang="ts"> <script lang="ts">
import { getPlatformString } from "@tslib/shortcuts"; import { getPlatformString } from "@tslib/shortcuts";
import IconButton from "../../components/IconButton.svelte"; import IconButton from "$lib/components/IconButton.svelte";
import Shortcut from "../../components/Shortcut.svelte"; import Shortcut from "$lib/components/Shortcut.svelte";
import WithState from "../../components/WithState.svelte"; import WithState from "$lib/components/WithState.svelte";
import { updateStateByKey } from "../../components/WithState.svelte"; import { updateStateByKey } from "$lib/components/WithState.svelte";
import { execCommand, queryCommandState } from "../../domlib"; import { execCommand, queryCommandState } from "$lib/domlib";
import { context as noteEditorContext } from "../NoteEditor.svelte"; import { context as noteEditorContext } from "../NoteEditor.svelte";
import { editingInputIsRichText } from "../rich-text-input"; import { editingInputIsRichText } from "../rich-text-input";

View File

@ -5,8 +5,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<script context="module" lang="ts"> <script context="module" lang="ts">
import type { Writable } from "svelte/store"; import type { Writable } from "svelte/store";
import { resetAllState, updateAllState } from "../../components/WithState.svelte"; import { resetAllState, updateAllState } from "$lib/components/WithState.svelte";
import type { DefaultSlotInterface } from "../../sveltelib/dynamic-slotting"; import type { DefaultSlotInterface } from "$lib/sveltelib/dynamic-slotting";
export function updateActiveButtons(event: Event) { export function updateActiveButtons(event: Event) {
updateAllState(event); updateAllState(event);
@ -39,7 +39,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
AddonButtons, AddonButtons,
}; };
import contextProperty from "../../sveltelib/context-property"; import contextProperty from "$lib/sveltelib/context-property";
const key = Symbol("editorToolbar"); const key = Symbol("editorToolbar");
const [context, setContextProperty] = contextProperty<EditorToolbarAPI>(key); const [context, setContextProperty] = contextProperty<EditorToolbarAPI>(key);
@ -51,9 +51,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { createEventDispatcher } from "svelte"; import { createEventDispatcher } from "svelte";
import { writable } from "svelte/store"; import { writable } from "svelte/store";
import ButtonToolbar from "../../components/ButtonToolbar.svelte"; import ButtonToolbar from "$lib/components/ButtonToolbar.svelte";
import DynamicallySlottable from "../../components/DynamicallySlottable.svelte"; import DynamicallySlottable from "$lib/components/DynamicallySlottable.svelte";
import Item from "../../components/Item.svelte"; import Item from "$lib/components/Item.svelte";
import BlockButtons from "./BlockButtons.svelte"; import BlockButtons from "./BlockButtons.svelte";
import ImageOcclusionButton from "./ImageOcclusionButton.svelte"; import ImageOcclusionButton from "./ImageOcclusionButton.svelte";
import InlineButtons from "./InlineButtons.svelte"; import InlineButtons from "./InlineButtons.svelte";

View File

@ -3,14 +3,15 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@generated/ftl";
import { bridgeCommand } from "@tslib/bridgecommand"; import { bridgeCommand } from "@tslib/bridgecommand";
import * as tr from "@tslib/ftl";
import { removeStyleProperties } from "@tslib/styling"; import { removeStyleProperties } from "@tslib/styling";
import { singleCallback } from "@tslib/typing"; import { singleCallback } from "@tslib/typing";
import { onMount } from "svelte"; import { onMount } from "svelte";
import IconButton from "../../components/IconButton.svelte"; import IconButton from "$lib/components/IconButton.svelte";
import type { FormattingNode, MatchType } from "../../domlib/surround"; import type { FormattingNode, MatchType } from "$lib/domlib/surround";
import { chevronDown } from "../icons"; import { chevronDown } from "../icons";
import { surrounder } from "../rich-text-input"; import { surrounder } from "../rich-text-input";
import ColorPicker from "./ColorPicker.svelte"; import ColorPicker from "./ColorPicker.svelte";

View File

@ -3,17 +3,21 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@tslib/ftl"; import * as tr from "@generated/ftl";
import ButtonGroup from "components/ButtonGroup.svelte";
import DynamicallySlottable from "components/DynamicallySlottable.svelte";
import IconButton from "components/IconButton.svelte";
import { ioImageLoadedStore, ioMaskEditorVisible } from "image-occlusion/store";
import ButtonGroup from "$lib/components/ButtonGroup.svelte";
import ButtonGroupItem, { import ButtonGroupItem, {
createProps, createProps,
setSlotHostContext, setSlotHostContext,
updatePropsList, updatePropsList,
} from "../../components/ButtonGroupItem.svelte"; } from "$lib/components/ButtonGroupItem.svelte";
import DynamicallySlottable from "$lib/components/DynamicallySlottable.svelte";
import IconButton from "$lib/components/IconButton.svelte";
import {
ioImageLoadedStore,
ioMaskEditorVisible,
} from "../../routes/image-occlusion/store";
import { mdiTableRefresh, mdiViewDashboard } from "./icons"; import { mdiTableRefresh, mdiViewDashboard } from "./icons";
export let api = {}; export let api = {};

View File

@ -3,9 +3,10 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import ButtonGroup from "../../components/ButtonGroup.svelte"; import ButtonGroup from "$lib/components/ButtonGroup.svelte";
import DynamicallySlottable from "../../components/DynamicallySlottable.svelte"; import DynamicallySlottable from "$lib/components/DynamicallySlottable.svelte";
import Item from "../../components/Item.svelte"; import Item from "$lib/components/Item.svelte";
import BoldButton from "./BoldButton.svelte"; import BoldButton from "./BoldButton.svelte";
import HighlightColorButton from "./HighlightColorButton.svelte"; import HighlightColorButton from "./HighlightColorButton.svelte";
import ItalicButton from "./ItalicButton.svelte"; import ItalicButton from "./ItalicButton.svelte";

View File

@ -3,10 +3,11 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@tslib/ftl"; import * as tr from "@generated/ftl";
import { removeStyleProperties } from "@tslib/styling"; import { removeStyleProperties } from "@tslib/styling";
import type { MatchType } from "../../domlib/surround"; import type { MatchType } from "$lib/domlib/surround";
import { italicIcon } from "./icons"; import { italicIcon } from "./icons";
import TextAttributeButton from "./TextAttributeButton.svelte"; import TextAttributeButton from "./TextAttributeButton.svelte";

View File

@ -3,15 +3,16 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@tslib/ftl"; import * as tr from "@generated/ftl";
import { getPlatformString } from "@tslib/shortcuts"; import { getPlatformString } from "@tslib/shortcuts";
import { wrapInternal } from "@tslib/wrap"; import { wrapInternal } from "@tslib/wrap";
import DropdownItem from "../../components/DropdownItem.svelte"; import DropdownItem from "$lib/components/DropdownItem.svelte";
import IconButton from "../../components/IconButton.svelte"; import IconButton from "$lib/components/IconButton.svelte";
import Popover from "../../components/Popover.svelte"; import Popover from "$lib/components/Popover.svelte";
import Shortcut from "../../components/Shortcut.svelte"; import Shortcut from "$lib/components/Shortcut.svelte";
import WithFloating from "../../components/WithFloating.svelte"; import WithFloating from "$lib/components/WithFloating.svelte";
import { mathjaxConfig } from "../../editable/mathjax-element"; import { mathjaxConfig } from "../../editable/mathjax-element";
import { context as noteEditorContext } from "../NoteEditor.svelte"; import { context as noteEditorContext } from "../NoteEditor.svelte";
import type { RichTextInputAPI } from "../rich-text-input"; import type { RichTextInputAPI } from "../rich-text-input";

View File

@ -3,19 +3,19 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@generated/ftl";
import { bridgeCommand } from "@tslib/bridgecommand"; import { bridgeCommand } from "@tslib/bridgecommand";
import * as tr from "@tslib/ftl";
import { getPlatformString } from "@tslib/shortcuts"; import { getPlatformString } from "@tslib/shortcuts";
import ButtonGroup from "../../components/ButtonGroup.svelte"; import ButtonGroup from "$lib/components/ButtonGroup.svelte";
import ButtonGroupItem, { import ButtonGroupItem, {
createProps, createProps,
setSlotHostContext, setSlotHostContext,
updatePropsList, updatePropsList,
} from "../../components/ButtonGroupItem.svelte"; } from "$lib/components/ButtonGroupItem.svelte";
import DynamicallySlottable from "../../components/DynamicallySlottable.svelte"; import DynamicallySlottable from "$lib/components/DynamicallySlottable.svelte";
import LabelButton from "../../components/LabelButton.svelte"; import LabelButton from "$lib/components/LabelButton.svelte";
import Shortcut from "../../components/Shortcut.svelte"; import Shortcut from "$lib/components/Shortcut.svelte";
export let api = {}; export let api = {};

View File

@ -3,14 +3,15 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@generated/ftl";
import { bridgeCommand } from "@tslib/bridgecommand"; import { bridgeCommand } from "@tslib/bridgecommand";
import * as tr from "@tslib/ftl";
import CheckBox from "../../components/CheckBox.svelte"; import CheckBox from "$lib/components/CheckBox.svelte";
import DropdownItem from "../../components/DropdownItem.svelte"; import DropdownItem from "$lib/components/DropdownItem.svelte";
import IconButton from "../../components/IconButton.svelte"; import IconButton from "$lib/components/IconButton.svelte";
import Popover from "../../components/Popover.svelte"; import Popover from "$lib/components/Popover.svelte";
import WithFloating from "../../components/WithFloating.svelte"; import WithFloating from "$lib/components/WithFloating.svelte";
import { mathjaxConfig } from "../../editable/mathjax-element"; import { mathjaxConfig } from "../../editable/mathjax-element";
import { shrinkImagesByDefault } from "../image-overlay/ImageOverlay.svelte"; import { shrinkImagesByDefault } from "../image-overlay/ImageOverlay.svelte";
import { closeHTMLTags } from "../plain-text-input/PlainTextInput.svelte"; import { closeHTMLTags } from "../plain-text-input/PlainTextInput.svelte";

View File

@ -3,13 +3,14 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import ButtonGroup from "../../components/ButtonGroup.svelte"; import ButtonGroup from "$lib/components/ButtonGroup.svelte";
import ButtonGroupItem, { import ButtonGroupItem, {
createProps, createProps,
setSlotHostContext, setSlotHostContext,
updatePropsList, updatePropsList,
} from "../../components/ButtonGroupItem.svelte"; } from "$lib/components/ButtonGroupItem.svelte";
import DynamicallySlottable from "../../components/DynamicallySlottable.svelte"; import DynamicallySlottable from "$lib/components/DynamicallySlottable.svelte";
import OptionsButton from "./OptionsButton.svelte"; import OptionsButton from "./OptionsButton.svelte";
export let api = {}; export let api = {};

View File

@ -3,19 +3,20 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@tslib/ftl"; import * as tr from "@generated/ftl";
import { altPressed, shiftPressed } from "@tslib/keys"; import { altPressed, shiftPressed } from "@tslib/keys";
import { getPlatformString } from "@tslib/shortcuts"; import { getPlatformString } from "@tslib/shortcuts";
import { singleCallback } from "@tslib/typing"; import { singleCallback } from "@tslib/typing";
import { onMount } from "svelte"; import { onMount } from "svelte";
import CheckBox from "../../components/CheckBox.svelte"; import CheckBox from "$lib/components/CheckBox.svelte";
import DropdownItem from "../../components/DropdownItem.svelte"; import DropdownItem from "$lib/components/DropdownItem.svelte";
import IconButton from "../../components/IconButton.svelte"; import IconButton from "$lib/components/IconButton.svelte";
import Popover from "../../components/Popover.svelte"; import Popover from "$lib/components/Popover.svelte";
import Shortcut from "../../components/Shortcut.svelte"; import Shortcut from "$lib/components/Shortcut.svelte";
import WithFloating from "../../components/WithFloating.svelte"; import WithFloating from "$lib/components/WithFloating.svelte";
import type { MatchType } from "../../domlib/surround"; import type { MatchType } from "$lib/domlib/surround";
import { chevronDown } from "../icons"; import { chevronDown } from "../icons";
import { surrounder } from "../rich-text-input"; import { surrounder } from "../rich-text-input";
import type { RemoveFormat } from "./EditorToolbar.svelte"; import type { RemoveFormat } from "./EditorToolbar.svelte";

View File

@ -3,10 +3,11 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@tslib/ftl"; import * as tr from "@generated/ftl";
import { removeStyleProperties } from "@tslib/styling"; import { removeStyleProperties } from "@tslib/styling";
import type { MatchType } from "../../domlib/surround"; import type { MatchType } from "$lib/domlib/surround";
import { subscriptIcon } from "./icons"; import { subscriptIcon } from "./icons";
import TextAttributeButton from "./TextAttributeButton.svelte"; import TextAttributeButton from "./TextAttributeButton.svelte";

View File

@ -3,10 +3,11 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@tslib/ftl"; import * as tr from "@generated/ftl";
import { removeStyleProperties } from "@tslib/styling"; import { removeStyleProperties } from "@tslib/styling";
import type { MatchType } from "../../domlib/surround"; import type { MatchType } from "$lib/domlib/surround";
import { superscriptIcon } from "./icons"; import { superscriptIcon } from "./icons";
import TextAttributeButton from "./TextAttributeButton.svelte"; import TextAttributeButton from "./TextAttributeButton.svelte";

View File

@ -3,21 +3,22 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@generated/ftl";
import { bridgeCommand } from "@tslib/bridgecommand"; import { bridgeCommand } from "@tslib/bridgecommand";
import * as tr from "@tslib/ftl";
import { promiseWithResolver } from "@tslib/promise"; import { promiseWithResolver } from "@tslib/promise";
import { registerPackage } from "@tslib/runtime-require"; import { registerPackage } from "@tslib/runtime-require";
import { getPlatformString } from "@tslib/shortcuts"; import { getPlatformString } from "@tslib/shortcuts";
import ButtonGroup from "../../components/ButtonGroup.svelte"; import ButtonGroup from "$lib/components/ButtonGroup.svelte";
import ButtonGroupItem, { import ButtonGroupItem, {
createProps, createProps,
setSlotHostContext, setSlotHostContext,
updatePropsList, updatePropsList,
} from "../../components/ButtonGroupItem.svelte"; } from "$lib/components/ButtonGroupItem.svelte";
import DynamicallySlottable from "../../components/DynamicallySlottable.svelte"; import DynamicallySlottable from "$lib/components/DynamicallySlottable.svelte";
import IconButton from "../../components/IconButton.svelte"; import IconButton from "$lib/components/IconButton.svelte";
import Shortcut from "../../components/Shortcut.svelte"; import Shortcut from "$lib/components/Shortcut.svelte";
import { context } from "../NoteEditor.svelte"; import { context } from "../NoteEditor.svelte";
import { setFormat } from "../old-editor-adapter"; import { setFormat } from "../old-editor-adapter";
import type { RichTextInputAPI } from "../rich-text-input"; import type { RichTextInputAPI } from "../rich-text-input";

View File

@ -7,10 +7,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { singleCallback } from "@tslib/typing"; import { singleCallback } from "@tslib/typing";
import { onMount } from "svelte"; import { onMount } from "svelte";
import IconButton from "../../components/IconButton.svelte"; import IconButton from "$lib/components/IconButton.svelte";
import Shortcut from "../../components/Shortcut.svelte"; import Shortcut from "$lib/components/Shortcut.svelte";
import WithState, { updateStateByKey } from "../../components/WithState.svelte"; import WithState, { updateStateByKey } from "$lib/components/WithState.svelte";
import type { MatchType } from "../../domlib/surround"; import type { MatchType } from "$lib/domlib/surround";
import { surrounder } from "../rich-text-input"; import { surrounder } from "../rich-text-input";
import { context as editorToolbarContext } from "./EditorToolbar.svelte"; import { context as editorToolbarContext } from "./EditorToolbar.svelte";

View File

@ -3,16 +3,17 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@generated/ftl";
import { bridgeCommand } from "@tslib/bridgecommand"; import { bridgeCommand } from "@tslib/bridgecommand";
import * as tr from "@tslib/ftl";
import { getPlatformString } from "@tslib/shortcuts"; import { getPlatformString } from "@tslib/shortcuts";
import { removeStyleProperties } from "@tslib/styling"; import { removeStyleProperties } from "@tslib/styling";
import { singleCallback } from "@tslib/typing"; import { singleCallback } from "@tslib/typing";
import { onMount } from "svelte"; import { onMount } from "svelte";
import IconButton from "../../components/IconButton.svelte"; import IconButton from "$lib/components/IconButton.svelte";
import Shortcut from "../../components/Shortcut.svelte"; import Shortcut from "$lib/components/Shortcut.svelte";
import type { FormattingNode, MatchType } from "../../domlib/surround"; import type { FormattingNode, MatchType } from "$lib/domlib/surround";
import { withFontColor } from "../helpers"; import { withFontColor } from "../helpers";
import { chevronDown } from "../icons"; import { chevronDown } from "../icons";
import { surrounder } from "../rich-text-input"; import { surrounder } from "../rich-text-input";

View File

@ -3,9 +3,10 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@tslib/ftl"; import * as tr from "@generated/ftl";
import type { MatchType } from "$lib/domlib/surround";
import type { MatchType } from "../../domlib/surround";
import { underlineIcon } from "./icons"; import { underlineIcon } from "./icons";
import TextAttributeButton from "./TextAttributeButton.svelte"; import TextAttributeButton from "./TextAttributeButton.svelte";

View File

@ -1,8 +1,6 @@
// Copyright: Ankitects Pty Ltd and contributors // Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
/// <reference types="../../lib/image-import" />
export { default as cogIcon } from "@mdi/svg/svg/cog.svg"; export { default as cogIcon } from "@mdi/svg/svg/cog.svg";
export { default as colorHelperIcon } from "@mdi/svg/svg/color-helper.svg"; export { default as colorHelperIcon } from "@mdi/svg/svg/color-helper.svg";
export { default as highlightColorIcon } from "@mdi/svg/svg/format-color-highlight.svg"; export { default as highlightColorIcon } from "@mdi/svg/svg/format-color-highlight.svg";

View File

@ -1,8 +1,6 @@
// Copyright: Ankitects Pty Ltd and contributors // Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
/// <reference types="../lib/image-import" />
export { default as alertIcon } from "@mdi/svg/svg/alert.svg"; export { default as alertIcon } from "@mdi/svg/svg/alert.svg";
export { default as chevronDown } from "@mdi/svg/svg/chevron-down.svg"; export { default as chevronDown } from "@mdi/svg/svg/chevron-down.svg";
export { default as chevronUp } from "@mdi/svg/svg/chevron-up.svg"; export { default as chevronUp } from "@mdi/svg/svg/chevron-up.svg";

View File

@ -3,12 +3,13 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@tslib/ftl"; import * as tr from "@generated/ftl";
import { removeStyleProperties } from "@tslib/styling"; import { removeStyleProperties } from "@tslib/styling";
import { createEventDispatcher } from "svelte"; import { createEventDispatcher } from "svelte";
import ButtonGroup from "../../components/ButtonGroup.svelte"; import ButtonGroup from "$lib/components/ButtonGroup.svelte";
import IconButton from "../../components/IconButton.svelte"; import IconButton from "$lib/components/IconButton.svelte";
import { floatLeftIcon, floatNoneIcon, floatRightIcon } from "./icons"; import { floatLeftIcon, floatNoneIcon, floatRightIcon } from "./icons";
export let image: HTMLImageElement; export let image: HTMLImageElement;

View File

@ -9,16 +9,17 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
</script> </script>
<script lang="ts"> <script lang="ts">
import * as tr from "@generated/ftl";
import { on } from "@tslib/events"; import { on } from "@tslib/events";
import * as tr from "@tslib/ftl";
import { removeStyleProperties } from "@tslib/styling"; import { removeStyleProperties } from "@tslib/styling";
import type { Callback } from "@tslib/typing"; import type { Callback } from "@tslib/typing";
import { tick } from "svelte"; import { tick } from "svelte";
import ButtonToolbar from "../../components/ButtonToolbar.svelte"; import ButtonToolbar from "$lib/components/ButtonToolbar.svelte";
import Popover from "../../components/Popover.svelte"; import Popover from "$lib/components/Popover.svelte";
import WithFloating from "../../components/WithFloating.svelte"; import WithFloating from "$lib/components/WithFloating.svelte";
import WithOverlay from "../../components/WithOverlay.svelte"; import WithOverlay from "$lib/components/WithOverlay.svelte";
import type { EditingInputAPI } from "../EditingArea.svelte"; import type { EditingInputAPI } from "../EditingArea.svelte";
import HandleBackground from "../HandleBackground.svelte"; import HandleBackground from "../HandleBackground.svelte";
import HandleControl from "../HandleControl.svelte"; import HandleControl from "../HandleControl.svelte";

View File

@ -3,13 +3,14 @@ Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
--> -->
<script lang="ts"> <script lang="ts">
import * as tr from "@generated/ftl";
import { directionKey } from "@tslib/context-keys"; import { directionKey } from "@tslib/context-keys";
import * as tr from "@tslib/ftl";
import { createEventDispatcher, getContext } from "svelte"; import { createEventDispatcher, getContext } from "svelte";
import type { Readable } from "svelte/store"; import type { Readable } from "svelte/store";
import ButtonGroup from "../../components/ButtonGroup.svelte"; import ButtonGroup from "$lib/components/ButtonGroup.svelte";
import IconButton from "../../components/IconButton.svelte"; import IconButton from "$lib/components/IconButton.svelte";
import { sizeActual, sizeClear, sizeMinimized } from "./icons"; import { sizeActual, sizeClear, sizeMinimized } from "./icons";
export let isSizeConstrained: boolean; export let isSizeConstrained: boolean;

View File

@ -1,7 +1,7 @@
/* Copyright: Ankitects Pty Ltd and contributors /* Copyright: Ankitects Pty Ltd and contributors
* License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */ * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */
@use "sass:color"; @use "sass:color";
@use "sass/button-mixins" as button; @use "../lib/sass/button-mixins" as button;
.linkb { .linkb {
$size: var(--buttons-size); $size: var(--buttons-size);

Some files were not shown because too many files have changed in this diff Show More