yanki
Version:
A CLI tool and TypeScript library to turn Markdown into Anki flashcards.
1,526 lines (1,368 loc) • 56.9 kB
TypeScript
//#region node_modules/.pnpm/type-fest@5.6.0/node_modules/type-fest/source/primitive.d.ts
/**
Matches any [primitive value](https://developer.mozilla.org/en-US/docs/Glossary/Primitive).
@category Type
*/
type Primitive = null | undefined | string | number | boolean | symbol | bigint;
//#endregion
//#region node_modules/.pnpm/type-fest@5.6.0/node_modules/type-fest/source/is-any.d.ts
/**
Returns a boolean for whether the given type is `any`.
@link https://stackoverflow.com/a/49928360/1490091
Useful in type utilities, such as disallowing `any`s to be passed to a function.
@example
```
import type {IsAny} from 'type-fest';
const typedObject = {a: 1, b: 2} as const;
const anyObject: any = {a: 1, b: 2};
function get<O extends (IsAny<O> extends true ? {} : Record<string, number>), K extends keyof O = keyof O>(object: O, key: K) {
return object[key];
}
const typedA = get(typedObject, 'a');
//=> 1
const anyA = get(anyObject, 'a');
//=> any
```
@category Type Guard
@category Utilities
*/
type IsAny<T> = 0 extends 1 & NoInfer<T> ? true : false;
//#endregion
//#region node_modules/.pnpm/type-fest@5.6.0/node_modules/type-fest/source/is-optional-key-of.d.ts
/**
Returns a boolean for whether the given key is an optional key of type.
This is useful when writing utility types or schema validators that need to differentiate `optional` keys.
@example
```
import type {IsOptionalKeyOf} from 'type-fest';
type User = {
name: string;
surname: string;
luckyNumber?: number;
};
type Admin = {
name: string;
surname?: string;
};
type T1 = IsOptionalKeyOf<User, 'luckyNumber'>;
//=> true
type T2 = IsOptionalKeyOf<User, 'name'>;
//=> false
type T3 = IsOptionalKeyOf<User, 'name' | 'luckyNumber'>;
//=> boolean
type T4 = IsOptionalKeyOf<User | Admin, 'name'>;
//=> false
type T5 = IsOptionalKeyOf<User | Admin, 'surname'>;
//=> boolean
```
@category Type Guard
@category Utilities
*/
type IsOptionalKeyOf<Type extends object, Key extends keyof Type> = IsAny<Type | Key> extends true ? never : Key extends keyof Type ? Type extends Record<Key, Type[Key]> ? false : true : false;
//#endregion
//#region node_modules/.pnpm/type-fest@5.6.0/node_modules/type-fest/source/optional-keys-of.d.ts
/**
Extract all optional keys from the given type.
This is useful when you want to create a new type that contains different type values for the optional keys only.
@example
```
import type {OptionalKeysOf, Except} from 'type-fest';
type User = {
name: string;
surname: string;
luckyNumber?: number;
};
const REMOVE_FIELD = Symbol('remove field symbol');
type UpdateOperation<Entity extends object> = Except<Partial<Entity>, OptionalKeysOf<Entity>> & {
[Key in OptionalKeysOf<Entity>]?: Entity[Key] | typeof REMOVE_FIELD;
};
const update1: UpdateOperation<User> = {
name: 'Alice',
};
const update2: UpdateOperation<User> = {
name: 'Bob',
luckyNumber: REMOVE_FIELD,
};
```
@category Utilities
*/
type OptionalKeysOf<Type extends object> = Type extends unknown // For distributing `Type`
? (keyof { [Key in keyof Type as IsOptionalKeyOf<Type, Key> extends false ? never : Key]: never }) & keyof Type // Intersect with `keyof Type` to ensure result of `OptionalKeysOf<Type>` is always assignable to `keyof Type`
: never;
//#endregion
//#region node_modules/.pnpm/type-fest@5.6.0/node_modules/type-fest/source/required-keys-of.d.ts
/**
Extract all required keys from the given type.
This is useful when you want to create a new type that contains different type values for the required keys only or use the list of keys for validation purposes, etc...
@example
```
import type {RequiredKeysOf} from 'type-fest';
declare function createValidation<
Entity extends object,
Key extends RequiredKeysOf<Entity> = RequiredKeysOf<Entity>,
>(field: Key, validator: (value: Entity[Key]) => boolean): (entity: Entity) => boolean;
type User = {
name: string;
surname: string;
luckyNumber?: number;
};
const validator1 = createValidation<User>('name', value => value.length < 25);
const validator2 = createValidation<User>('surname', value => value.length < 25);
// @ts-expect-error
const validator3 = createValidation<User>('luckyNumber', value => value > 0);
// Error: Argument of type '"luckyNumber"' is not assignable to parameter of type '"name" | "surname"'.
```
@category Utilities
*/
type RequiredKeysOf<Type extends object> = Type extends unknown // For distributing `Type`
? Exclude<keyof Type, OptionalKeysOf<Type>> : never;
//#endregion
//#region node_modules/.pnpm/type-fest@5.6.0/node_modules/type-fest/source/is-never.d.ts
/**
Returns a boolean for whether the given type is `never`.
@link https://github.com/microsoft/TypeScript/issues/31751#issuecomment-498526919
@link https://stackoverflow.com/a/53984913/10292952
@link https://www.zhenghao.io/posts/ts-never
Useful in type utilities, such as checking if something does not occur.
@example
```
import type {IsNever, And} from 'type-fest';
type A = IsNever<never>;
//=> true
type B = IsNever<any>;
//=> false
type C = IsNever<unknown>;
//=> false
type D = IsNever<never[]>;
//=> false
type E = IsNever<object>;
//=> false
type F = IsNever<string>;
//=> false
```
@example
```
import type {IsNever} from 'type-fest';
type IsTrue<T> = T extends true ? true : false;
// When a distributive conditional is instantiated with `never`, the entire conditional results in `never`.
type A = IsTrue<never>;
//=> never
// If you don't want that behaviour, you can explicitly add an `IsNever` check before the distributive conditional.
type IsTrueFixed<T> =
IsNever<T> extends true ? false : T extends true ? true : false;
type B = IsTrueFixed<never>;
//=> false
```
@category Type Guard
@category Utilities
*/
type IsNever<T> = [T] extends [never] ? true : false;
//#endregion
//#region node_modules/.pnpm/type-fest@5.6.0/node_modules/type-fest/source/if.d.ts
/**
An if-else-like type that resolves depending on whether the given `boolean` type is `true` or `false`.
Use-cases:
- You can use this in combination with `Is*` types to create an if-else-like experience. For example, `If<IsAny<any>, 'is any', 'not any'>`.
Note:
- Returns a union of if branch and else branch if the given type is `boolean` or `any`. For example, `If<boolean, 'Y', 'N'>` will return `'Y' | 'N'`.
- Returns the else branch if the given type is `never`. For example, `If<never, 'Y', 'N'>` will return `'N'`.
@example
```
import type {If} from 'type-fest';
type A = If<true, 'yes', 'no'>;
//=> 'yes'
type B = If<false, 'yes', 'no'>;
//=> 'no'
type C = If<boolean, 'yes', 'no'>;
//=> 'yes' | 'no'
type D = If<any, 'yes', 'no'>;
//=> 'yes' | 'no'
type E = If<never, 'yes', 'no'>;
//=> 'no'
```
@example
```
import type {If, IsAny, IsNever} from 'type-fest';
type A = If<IsAny<unknown>, 'is any', 'not any'>;
//=> 'not any'
type B = If<IsNever<never>, 'is never', 'not never'>;
//=> 'is never'
```
@example
```
import type {If, IsEqual} from 'type-fest';
type IfEqual<T, U, IfBranch, ElseBranch> = If<IsEqual<T, U>, IfBranch, ElseBranch>;
type A = IfEqual<string, string, 'equal', 'not equal'>;
//=> 'equal'
type B = IfEqual<string, number, 'equal', 'not equal'>;
//=> 'not equal'
```
Note: Sometimes using the `If` type can make an implementation non–tail-recursive, which can impact performance. In such cases, it’s better to use a conditional directly. Refer to the following example:
@example
```
import type {If, IsEqual, StringRepeat} from 'type-fest';
type HundredZeroes = StringRepeat<'0', 100>;
// The following implementation is not tail recursive
type Includes<S extends string, Char extends string> =
S extends `${infer First}${infer Rest}`
? If<IsEqual<First, Char>,
'found',
Includes<Rest, Char>>
: 'not found';
// Hence, instantiations with long strings will fail
// @ts-expect-error
type Fails = Includes<HundredZeroes, '1'>;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Error: Type instantiation is excessively deep and possibly infinite.
// However, if we use a simple conditional instead of `If`, the implementation becomes tail-recursive
type IncludesWithoutIf<S extends string, Char extends string> =
S extends `${infer First}${infer Rest}`
? IsEqual<First, Char> extends true
? 'found'
: IncludesWithoutIf<Rest, Char>
: 'not found';
// Now, instantiations with long strings will work
type Works = IncludesWithoutIf<HundredZeroes, '1'>;
//=> 'not found'
```
@category Type Guard
@category Utilities
*/
type If<Type extends boolean, IfBranch, ElseBranch> = IsNever<Type> extends true ? ElseBranch : Type extends true ? IfBranch : ElseBranch;
//#endregion
//#region node_modules/.pnpm/type-fest@5.6.0/node_modules/type-fest/source/internal/type.d.ts
/**
Matches any primitive, `void`, `Date`, or `RegExp` value.
*/
type BuiltIns = Primitive | void | Date | RegExp;
/**
Test if the given function has multiple call signatures.
Needed to handle the case of a single call signature with properties.
Multiple call signatures cannot currently be supported due to a TypeScript limitation.
@see https://github.com/microsoft/TypeScript/issues/29732
*/
type HasMultipleCallSignatures<T extends (...arguments_: any[]) => unknown> = T extends {
(...arguments_: infer A): unknown;
(...arguments_: infer B): unknown;
} ? B extends A ? A extends B ? false : true : true : false;
//#endregion
//#region node_modules/.pnpm/type-fest@5.6.0/node_modules/type-fest/source/simplify.d.ts
/**
Useful to flatten the type output to improve type hints shown in editors. And also to transform an interface into a type to aide with assignability.
@example
```
import type {Simplify} from 'type-fest';
type PositionProps = {
top: number;
left: number;
};
type SizeProps = {
width: number;
height: number;
};
// In your editor, hovering over `Props` will show a flattened object with all the properties.
type Props = Simplify<PositionProps & SizeProps>;
```
Sometimes it is desired to pass a value as a function argument that has a different type. At first inspection it may seem assignable, and then you discover it is not because the `value`'s type definition was defined as an interface. In the following example, `fn` requires an argument of type `Record<string, unknown>`. If the value is defined as a literal, then it is assignable. And if the `value` is defined as type using the `Simplify` utility the value is assignable. But if the `value` is defined as an interface, it is not assignable because the interface is not sealed and elsewhere a non-string property could be added to the interface.
If the type definition must be an interface (perhaps it was defined in a third-party npm package), then the `value` can be defined as `const value: Simplify<SomeInterface> = ...`. Then `value` will be assignable to the `fn` argument. Or the `value` can be cast as `Simplify<SomeInterface>` if you can't re-declare the `value`.
@example
```
import type {Simplify} from 'type-fest';
interface SomeInterface {
foo: number;
bar?: string;
baz: number | undefined;
}
type SomeType = {
foo: number;
bar?: string;
baz: number | undefined;
};
const literal = {foo: 123, bar: 'hello', baz: 456};
const someType: SomeType = literal;
const someInterface: SomeInterface = literal;
declare function fn(object: Record<string, unknown>): void;
fn(literal); // Good: literal object type is sealed
fn(someType); // Good: type is sealed
// @ts-expect-error
fn(someInterface); // Error: Index signature for type 'string' is missing in type 'someInterface'. Because `interface` can be re-opened
fn(someInterface as Simplify<SomeInterface>); // Good: transform an `interface` into a `type`
```
@link https://github.com/microsoft/TypeScript/issues/15300
@see {@link SimplifyDeep}
@category Object
*/
type Simplify<T> = { [KeyType in keyof T]: T[KeyType] } & {};
//#endregion
//#region node_modules/.pnpm/type-fest@5.6.0/node_modules/type-fest/source/is-equal.d.ts
/**
Returns a boolean for whether the two given types are equal.
@link https://github.com/microsoft/TypeScript/issues/27024#issuecomment-421529650
@link https://stackoverflow.com/questions/68961864/how-does-the-equals-work-in-typescript/68963796#68963796
Use-cases:
- If you want to make a conditional branch based on the result of a comparison of two types.
@example
```
import type {IsEqual} from 'type-fest';
// This type returns a boolean for whether the given array includes the given item.
// `IsEqual` is used to compare the given array at position 0 and the given item and then return true if they are equal.
type Includes<Value extends readonly any[], Item> =
Value extends readonly [Value[0], ...infer rest]
? IsEqual<Value[0], Item> extends true
? true
: Includes<rest, Item>
: false;
```
@category Type Guard
@category Utilities
*/
type IsEqual<A, B> = [A] extends [B] ? [B] extends [A] ? _IsEqual<A, B> : false : false;
// This version fails the `equalWrappedTupleIntersectionToBeNeverAndNeverExpanded` test in `test-d/is-equal.ts`.
type _IsEqual<A, B> = (<G>() => G extends A & G | G ? 1 : 2) extends (<G>() => G extends B & G | G ? 1 : 2) ? true : false;
//#endregion
//#region node_modules/.pnpm/type-fest@5.6.0/node_modules/type-fest/source/omit-index-signature.d.ts
/**
Omit any index signatures from the given object type, leaving only explicitly defined properties.
This is the counterpart of `PickIndexSignature`.
Use-cases:
- Remove overly permissive signatures from third-party types.
This type was taken from this [StackOverflow answer](https://stackoverflow.com/a/68261113/420747).
It relies on the fact that an empty object (`{}`) is assignable to an object with just an index signature, like `Record<string, unknown>`, but not to an object with explicitly defined keys, like `Record<'foo' | 'bar', unknown>`.
(The actual value type, `unknown`, is irrelevant and could be any type. Only the key type matters.)
```
const indexed: Record<string, unknown> = {}; // Allowed
// @ts-expect-error
const keyed: Record<'foo', unknown> = {}; // Error
// TS2739: Type '{}' is missing the following properties from type 'Record<"foo" | "bar", unknown>': foo, bar
```
Instead of causing a type error like the above, you can also use a [conditional type](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html) to test whether a type is assignable to another:
```
type Indexed = {} extends Record<string, unknown>
? '✅ `{}` is assignable to `Record<string, unknown>`'
: '❌ `{}` is NOT assignable to `Record<string, unknown>`';
type IndexedResult = Indexed;
//=> '✅ `{}` is assignable to `Record<string, unknown>`'
type Keyed = {} extends Record<'foo' | 'bar', unknown>
? '✅ `{}` is assignable to `Record<\'foo\' | \'bar\', unknown>`'
: '❌ `{}` is NOT assignable to `Record<\'foo\' | \'bar\', unknown>`';
type KeyedResult = Keyed;
//=> '❌ `{}` is NOT assignable to `Record<\'foo\' | \'bar\', unknown>`'
```
Using a [mapped type](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html#further-exploration), you can then check for each `KeyType` of `ObjectType`...
```
type OmitIndexSignature<ObjectType> = {
[KeyType in keyof ObjectType // Map each key of `ObjectType`...
]: ObjectType[KeyType]; // ...to its original value, i.e. `OmitIndexSignature<Foo> == Foo`.
};
```
...whether an empty object (`{}`) would be assignable to an object with that `KeyType` (`Record<KeyType, unknown>`)...
```
type OmitIndexSignature<ObjectType> = {
[KeyType in keyof ObjectType
// Is `{}` assignable to `Record<KeyType, unknown>`?
as {} extends Record<KeyType, unknown>
? never // ✅ `{}` is assignable to `Record<KeyType, unknown>`
: KeyType // ❌ `{}` is NOT assignable to `Record<KeyType, unknown>`
]: ObjectType[KeyType];
};
```
If `{}` is assignable, it means that `KeyType` is an index signature and we want to remove it. If it is not assignable, `KeyType` is a "real" key and we want to keep it.
@example
```
import type {OmitIndexSignature} from 'type-fest';
type Example = {
// These index signatures will be removed.
[x: string]: any;
[x: number]: any;
[x: symbol]: any;
[x: `head-${string}`]: string;
[x: `${string}-tail`]: string;
[x: `head-${string}-tail`]: string;
[x: `${bigint}`]: string;
[x: `embedded-${number}`]: string;
// These explicitly defined keys will remain.
foo: 'bar';
qux?: 'baz';
};
type ExampleWithoutIndexSignatures = OmitIndexSignature<Example>;
//=> {foo: 'bar'; qux?: 'baz'}
```
@see {@link PickIndexSignature}
@category Object
*/
type OmitIndexSignature<ObjectType> = { [KeyType in keyof ObjectType as {} extends Record<KeyType, unknown> ? never : KeyType]: ObjectType[KeyType] };
//#endregion
//#region node_modules/.pnpm/type-fest@5.6.0/node_modules/type-fest/source/pick-index-signature.d.ts
/**
Pick only index signatures from the given object type, leaving out all explicitly defined properties.
This is the counterpart of `OmitIndexSignature`.
@example
```
import type {PickIndexSignature} from 'type-fest';
declare const symbolKey: unique symbol;
type Example = {
// These index signatures will remain.
[x: string]: unknown;
[x: number]: unknown;
[x: symbol]: unknown;
[x: `head-${string}`]: string;
[x: `${string}-tail`]: string;
[x: `head-${string}-tail`]: string;
[x: `${bigint}`]: string;
[x: `embedded-${number}`]: string;
// These explicitly defined keys will be removed.
['kebab-case-key']: string;
[symbolKey]: string;
foo: 'bar';
qux?: 'baz';
};
type ExampleIndexSignature = PickIndexSignature<Example>;
// {
// [x: string]: unknown;
// [x: number]: unknown;
// [x: symbol]: unknown;
// [x: `head-${string}`]: string;
// [x: `${string}-tail`]: string;
// [x: `head-${string}-tail`]: string;
// [x: `${bigint}`]: string;
// [x: `embedded-${number}`]: string;
// }
```
@see {@link OmitIndexSignature}
@category Object
*/
type PickIndexSignature<ObjectType> = { [KeyType in keyof ObjectType as {} extends Record<KeyType, unknown> ? KeyType : never]: ObjectType[KeyType] };
//#endregion
//#region node_modules/.pnpm/type-fest@5.6.0/node_modules/type-fest/source/merge.d.ts
// Merges two objects without worrying about index signatures.
type SimpleMerge<Destination, Source> = Simplify<{ [Key in keyof Destination as Key extends keyof Source ? never : Key]: Destination[Key] } & Source>;
/**
Merge two types into a new type. Keys of the second type overrides keys of the first type.
This is different from the TypeScript `&` (intersection) operator. With `&`, conflicting property types are intersected, which often results in `never`. For example, `{a: string} & {a: number}` makes `a` become `string & number`, which resolves to `never`. With `Merge`, the second type's keys cleanly override the first, so `Merge<{a: string}, {a: number}>` gives `{a: number}` as expected. `Merge` also produces a flattened type (via `Simplify`), making it more readable in IDE tooltips compared to `A & B`.
@example
```
import type {Merge} from 'type-fest';
type Foo = {
a: string;
b: number;
};
type Bar = {
a: number; // Conflicts with Foo['a']
c: boolean;
};
// With `&`, `a` becomes `string & number` which is `never`. Not what you want.
type WithIntersection = (Foo & Bar)['a'];
//=> never
// With `Merge`, `a` is cleanly overridden to `number`.
type WithMerge = Merge<Foo, Bar>['a'];
//=> number
```
@example
```
import type {Merge} from 'type-fest';
type Foo = {
[x: string]: unknown;
[x: number]: unknown;
foo: string;
bar: symbol;
};
type Bar = {
[x: number]: number;
[x: symbol]: unknown;
bar: Date;
baz: boolean;
};
export type FooBar = Merge<Foo, Bar>;
//=> {
// [x: string]: unknown;
// [x: number]: number;
// [x: symbol]: unknown;
// foo: string;
// bar: Date;
// baz: boolean;
// }
```
Note: If you want a merge type that more accurately reflects the runtime behavior of object spread or `Object.assign`, refer to the {@link ObjectMerge} type.
@see {@link ObjectMerge}
@category Object
*/
type Merge<Destination, Source> = Destination extends unknown // For distributing `Destination`
? Source extends unknown // For distributing `Source`
? If<IsEqual<Destination, Source>, Destination, _Merge<Destination, Source>> : never // Should never happen
: never;
// Should never happen
type _Merge<Destination, Source> = Simplify<SimpleMerge<PickIndexSignature<Destination>, PickIndexSignature<Source>> & SimpleMerge<OmitIndexSignature<Destination>, OmitIndexSignature<Source>>>;
//#endregion
//#region node_modules/.pnpm/type-fest@5.6.0/node_modules/type-fest/source/internal/object.d.ts
/**
Merges user specified options with default options.
@example
```
type PathsOptions = {maxRecursionDepth?: number; leavesOnly?: boolean};
type DefaultPathsOptions = {maxRecursionDepth: 10; leavesOnly: false};
type SpecifiedOptions = {leavesOnly: true};
type Result = ApplyDefaultOptions<PathsOptions, DefaultPathsOptions, SpecifiedOptions>;
//=> {maxRecursionDepth: 10; leavesOnly: true}
```
@example
```
// Complains if default values are not provided for optional options
type PathsOptions = {maxRecursionDepth?: number; leavesOnly?: boolean};
type DefaultPathsOptions = {maxRecursionDepth: 10};
type SpecifiedOptions = {};
type Result = ApplyDefaultOptions<PathsOptions, DefaultPathsOptions, SpecifiedOptions>;
// ~~~~~~~~~~~~~~~~~~~
// Property 'leavesOnly' is missing in type 'DefaultPathsOptions' but required in type '{ maxRecursionDepth: number; leavesOnly: boolean; }'.
```
@example
```
// Complains if an option's default type does not conform to the expected type
type PathsOptions = {maxRecursionDepth?: number; leavesOnly?: boolean};
type DefaultPathsOptions = {maxRecursionDepth: 10; leavesOnly: 'no'};
type SpecifiedOptions = {};
type Result = ApplyDefaultOptions<PathsOptions, DefaultPathsOptions, SpecifiedOptions>;
// ~~~~~~~~~~~~~~~~~~~
// Types of property 'leavesOnly' are incompatible. Type 'string' is not assignable to type 'boolean'.
```
@example
```
// Complains if an option's specified type does not conform to the expected type
type PathsOptions = {maxRecursionDepth?: number; leavesOnly?: boolean};
type DefaultPathsOptions = {maxRecursionDepth: 10; leavesOnly: false};
type SpecifiedOptions = {leavesOnly: 'yes'};
type Result = ApplyDefaultOptions<PathsOptions, DefaultPathsOptions, SpecifiedOptions>;
// ~~~~~~~~~~~~~~~~
// Types of property 'leavesOnly' are incompatible. Type 'string' is not assignable to type 'boolean'.
```
*/
type ApplyDefaultOptions<Options extends object, Defaults extends Simplify<Omit<Required<Options>, RequiredKeysOf<Options>> & Partial<Record<RequiredKeysOf<Options>, never>>>, SpecifiedOptions extends Options> = If<IsAny<SpecifiedOptions>, Defaults, If<IsNever<SpecifiedOptions>, Defaults, Simplify<Merge<Defaults, { [Key in keyof SpecifiedOptions as Key extends OptionalKeysOf<Options> ? undefined extends SpecifiedOptions[Key] ? never : Key : Key]: SpecifiedOptions[Key] }> & Required<Options>>>>;
//#endregion
//#region node_modules/.pnpm/type-fest@5.6.0/node_modules/type-fest/source/partial-deep.d.ts
/**
@see {@link PartialDeep}
*/
type PartialDeepOptions = {
/**
Whether to affect the individual elements of arrays and tuples.
@default false
*/
readonly recurseIntoArrays?: boolean;
/**
Allows `undefined` values in non-tuple arrays.
- When set to `true`, elements of non-tuple arrays can be `undefined`.
- When set to `false`, only explicitly defined elements are allowed in non-tuple arrays, ensuring stricter type checking.
@default false
@example
You can allow `undefined` values in non-tuple arrays by passing `{recurseIntoArrays: true; allowUndefinedInNonTupleArrays: true}` as the second type argument:
```
import type {PartialDeep} from 'type-fest';
type Settings = {
languages: string[];
};
declare const partialSettings: PartialDeep<Settings, {recurseIntoArrays: true; allowUndefinedInNonTupleArrays: true}>;
partialSettings.languages = [undefined]; // OK
```
*/
readonly allowUndefinedInNonTupleArrays?: boolean;
};
type DefaultPartialDeepOptions = {
recurseIntoArrays: false;
allowUndefinedInNonTupleArrays: false;
};
/**
Create a deeply optional version of another type.
Use-cases:
- Merging a default settings/config object with another object, the second object would be a deep partial of the default object.
- Mocking and testing complex entities, where populating an entire object with its keys would be redundant in terms of the mock or test.
Use [`Partial<T>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype) if you only need one level deep.
@example
```
import type {PartialDeep} from 'type-fest';
let settings = {
textEditor: {
fontSize: 14,
fontColor: '#000000',
fontWeight: 400,
},
autocomplete: false,
autosave: true,
};
const applySavedSettings = (savedSettings: PartialDeep<typeof settings>) => (
{...settings, ...savedSettings, textEditor: {...settings.textEditor, ...savedSettings.textEditor}}
);
settings = applySavedSettings({textEditor: {fontWeight: 500}});
```
By default, this does not affect elements in array and tuple types. You can change this by passing `{recurseIntoArrays: true}` as the second type argument:
```
import type {PartialDeep} from 'type-fest';
type Shape = {
dimensions: [number, number];
};
const partialShape: PartialDeep<Shape, {recurseIntoArrays: true}> = {
dimensions: [], // OK
};
partialShape.dimensions = [15]; // OK
```
@see {@link PartialDeepOptions}
@category Object
@category Array
@category Set
@category Map
*/
type PartialDeep<T, Options extends PartialDeepOptions = {}> = _PartialDeep<T, ApplyDefaultOptions<PartialDeepOptions, DefaultPartialDeepOptions, Options>>;
type _PartialDeep<T, Options extends Required<PartialDeepOptions>> = T extends BuiltIns | ((new (...arguments_: any[]) => unknown)) ? T : T extends Map<infer KeyType, infer ValueType> ? PartialMapDeep<KeyType, ValueType, Options> : T extends Set<infer ItemType> ? PartialSetDeep<ItemType, Options> : T extends ReadonlyMap<infer KeyType, infer ValueType> ? PartialReadonlyMapDeep<KeyType, ValueType, Options> : T extends ReadonlySet<infer ItemType> ? PartialReadonlySetDeep<ItemType, Options> : T extends ((...arguments_: any[]) => unknown) ? IsNever<keyof T> extends true ? T // For functions with no properties
: HasMultipleCallSignatures<T> extends true ? T : ((...arguments_: Parameters<T>) => ReturnType<T>) & PartialObjectDeep<T, Options> : T extends object ? T extends ReadonlyArray<infer ItemType> // Test for arrays/tuples, per https://github.com/microsoft/TypeScript/issues/35156
? Options['recurseIntoArrays'] extends true ? ItemType[] extends T // Test for arrays (non-tuples) specifically
? readonly ItemType[] extends T // Differentiate readonly and mutable arrays
? ReadonlyArray<_PartialDeep<Options['allowUndefinedInNonTupleArrays'] extends false ? ItemType : ItemType | undefined, Options>> : Array<_PartialDeep<Options['allowUndefinedInNonTupleArrays'] extends false ? ItemType : ItemType | undefined, Options>> : PartialObjectDeep<T, Options> // Tuples behave properly
: T // If they don't opt into array testing, just use the original type
: PartialObjectDeep<T, Options> : unknown;
/**
Same as `PartialDeep`, but accepts only `Map`s and as inputs. Internal helper for `PartialDeep`.
*/
type PartialMapDeep<KeyType, ValueType, Options extends Required<PartialDeepOptions>> = {} & Map<_PartialDeep<KeyType, Options>, _PartialDeep<ValueType, Options>>;
/**
Same as `PartialDeep`, but accepts only `Set`s as inputs. Internal helper for `PartialDeep`.
*/
type PartialSetDeep<T, Options extends Required<PartialDeepOptions>> = {} & Set<_PartialDeep<T, Options>>;
/**
Same as `PartialDeep`, but accepts only `ReadonlyMap`s as inputs. Internal helper for `PartialDeep`.
*/
type PartialReadonlyMapDeep<KeyType, ValueType, Options extends Required<PartialDeepOptions>> = {} & ReadonlyMap<_PartialDeep<KeyType, Options>, _PartialDeep<ValueType, Options>>;
/**
Same as `PartialDeep`, but accepts only `ReadonlySet`s as inputs. Internal helper for `PartialDeep`.
*/
type PartialReadonlySetDeep<T, Options extends Required<PartialDeepOptions>> = {} & ReadonlySet<_PartialDeep<T, Options>>;
/**
Same as `PartialDeep`, but accepts only `object`s as inputs. Internal helper for `PartialDeep`.
*/
type PartialObjectDeep<ObjectType extends object, Options extends Required<PartialDeepOptions>> = { [KeyType in keyof ObjectType]?: _PartialDeep<ObjectType[KeyType], Options> };
//#endregion
//#region node_modules/.pnpm/yanki-connect@4.0.5/node_modules/yanki-connect/dist/index.d.ts
//#region src/types/deck.d.ts
type DeckStats = {
deck_id: number;
learn_count: number;
name: string;
new_count: number;
review_count: number;
total_in_deck: number;
};
type DeckConfig = {
autoplay: boolean;
dyn: 1 | false;
id: number;
lapse: {
delays: number[];
leechAction: number;
leechFails: number;
minInt: number;
mult: number;
};
maxTaken: number;
mod: number;
name: string;
new: {
bury: boolean;
delays: number[];
initialFactor: number;
ints: number[];
order: number;
perDay: number;
separate: boolean;
};
replayq: boolean;
rev: {
bury: boolean;
ease4: number;
fuzz: number;
ivlFct: number;
maxIvl: number;
minSpace: number;
perDay: number;
};
timer: number;
usn: number;
};
type DeckRequests = Request<'changeDeck', 6, {
cards: number[];
deck: string;
}> | Request<'cloneDeckConfigId', 6, {
cloneFrom: number;
name: string;
}, false | number> | Request<'createDeck', 6, {
deck: string;
}, number> | Request<'deckNames', 6, never, string[]> | Request<'deckNamesAndIds', 6, never, Record<string, number>> | Request<'deleteDecks', 6, {
cardsToo: true;
decks: string[];
}> | Request<'getDeckConfig', 6, {
deck: string;
}, DeckConfig> | Request<'getDecks', 6, Record<'cards', number[]>, Record<string, number[]>> | Request<'getDeckStats', 6, {
decks: string[];
}, Record<string, DeckStats>> | Request<'removeDeckConfigId', 6, {
configId: number;
}, boolean> | Request<'saveDeckConfig', 6, {
config: DeckConfig;
}, boolean> | Request<'setDeckConfigId', 6, {
configId: number;
decks: string[];
}, boolean>; //#endregion
//#region src/types/note.d.ts
type NoteModel = 'Basic' | 'Basic (and reversed card)' | 'Basic (type in the answer)' | 'Cloze' | (string & {});
type NoteMedia = {
data?: string;
fields?: string[];
filename: string;
path?: string;
skipHash?: string;
url?: string;
};
type Note = {
audio?: NoteMedia[];
deckName: string;
fields: Record<string, string>;
modelName: NoteModel;
picture?: NoteMedia[];
tags?: string[];
video?: NoteMedia[];
};
type NoteWithCreationOptions = Note & {
options?: {
allowDuplicate?: boolean;
duplicateScope?: 'deck' | (string & {});
duplicateScopeOptions?: {
checkAllModels?: boolean;
checkChildren?: boolean;
deckName?: null | string;
};
};
};
type NoteRequests = Request<'addNote', 6, {
note: NoteWithCreationOptions;
}, null | number> | Request<'addNotes', 6, {
notes: NoteWithCreationOptions[];
}, Array<null | string> | null> | Request<'addTags', 6, {
notes: number[];
tags: string;
}> | Request<'canAddNotes', 6, {
notes: NoteWithCreationOptions[];
}, boolean[]> | Request<'canAddNotesWithErrorDetail', 6, {
notes: NoteWithCreationOptions[];
}, Array<{
canAdd: false;
error: string;
} | {
canAdd: true;
}>> | Request<'clearUnusedTags', 6, never, string[]> | Request<'deleteNotes', 6, {
notes: number[];
}> | Request<'findNotes', 6, {
query: string;
}, number[]> | Request<'getNoteTags', 6, {
note: number;
}, string[]> | Request<'getTags', 6, never, string[]> | Request<'notesInfo', 6, {
notes: number[];
}, Array<{
cards: number[];
fields: Record<string, {
order: number;
value: string;
}>;
mod: number;
modelName: string;
noteId: number;
profile: string;
tags: string[];
}>> | Request<'notesModTime', 6, {
notes: number[];
}, Array<{
mod: number;
noteId: number;
}>> | Request<'removeEmptyNotes', 6> | Request<'removeTags', 6, {
notes: number[];
tags: string;
}> | Request<'replaceTags', 6, {
notes: number[];
replace_with_tag: string;
tag_to_replace: string;
}> | Request<'replaceTagsInAllNotes', 6, {
replace_with_tag: string;
tag_to_replace: string;
}> | Request<'updateNote', 6, {
note: {
audio?: NoteMedia[];
fields: Record<string, string>;
id: number;
picture?: NoteMedia[];
tags?: string[];
video?: NoteMedia[];
} | {
fields?: Record<string, string>;
id: number;
tags: string[];
};
}> | Request<'updateNoteFields', 6, {
note: {
audio?: NoteMedia[];
fields: Record<string, string>;
id: number;
picture?: NoteMedia[];
video?: NoteMedia[];
};
}> | Request<'updateNoteModel', 6, {
note: {
fields: Record<string, string>;
id: number;
modelName: string;
tags: string[];
};
}> | Request<'updateNoteTags', 6, {
note: number;
tags: string[];
}>; //#endregion
//#region src/types/graphical.d.ts
type GraphicalRequests = Request<'guiAddCards', 6, {
note: Note;
}, number> | Request<'guiAnswerCard', 6, {
ease: number;
}, boolean> | Request<'guiBrowse', 6, {
query: string;
reorderCards?: {
columnId: CardBrowserColumns;
order: 'ascending' | 'descending';
};
}, number[]> | Request<'guiCheckDatabase', 6, never, true> | Request<'guiCurrentCard', 6, never, CardInfo | null> | Request<'guiDeckBrowser', 6> | Request<'guiDeckOverview', 6, {
name: string;
}, boolean> | Request<'guiDeckReview', 6, {
name: string;
}, boolean> | Request<'guiEditNote', 6, {
note: number;
}> | Request<'guiExitAnki', 6> | Request<'guiImportFile', 6, {
path: string;
}> | Request<'guiPlayAudio', 6, never, true> | Request<'guiSelectCard', 6, {
card: number;
}, boolean> | Request<'guiSelectedNotes', 6, never, number[]> | Request<'guiSelectNote', 6, {
note: number;
}, boolean> | Request<'guiShowAnswer', 6, never, boolean> | Request<'guiShowQuestion', 6, never, boolean> | Request<'guiStartCardTimer', 6, never, true> | Request<'guiUndo', 6, never, boolean>; //#endregion
//#region src/types/media.d.ts
type MediaRequests = Request<'deleteMediaFile', 6, {
filename: string;
}> | Request<'getMediaDirPath', 6, never, string> | Request<'getMediaFilesNames', 6, {
pattern: string;
}, string[]> | Request<'retrieveMediaFile', 6, {
filename: string;
}, false | string> | Request<'storeMediaFile', 6, {
data?: string;
deleteExisting?: boolean;
filename: string;
path?: string;
url?: string;
}, string>; //#endregion
//#region src/types/miscellaneous.d.ts
type MiscellaneousRequests = Request<'apiReflect', 6, {
actions: null | string[];
scopes: Array<'actions'>;
}, {
actions: string[];
scopes: string[];
}> | Request<'exportPackage', 6, {
deck: string;
includeSched?: boolean;
path: string;
}, boolean> | Request<'getActiveProfile', 6, never, string> | Request<'getProfiles', 6, never, string[]> | Request<'importPackage', 6, {
path: string;
}, boolean> | Request<'loadProfile', 6, {
name: string;
}, true> | Request<'multi', 6, // Crazy, have to call this experimental
{
actions: Array<{
action: Requests['action'];
params?: Requests['params'];
version?: number;
}>;
}, Array<Requests['response'] | {
error: null | string;
result: Requests['response'];
}>> | Request<'reloadCollection', 6> | Request<'requestPermission', 6, never, {
permission: 'denied';
} | {
permission: 'granted';
requireApiKey: boolean;
version: boolean;
}> | Request<'sync', 6> | Request<'version', 6, never, number>; //#endregion
//#region src/types/model.d.ts
type ModelField = {
collapsed: boolean;
description: string;
excludeFromSearch: boolean;
font: string;
id: number;
name: string;
ord: number;
plainText: boolean;
preventDeletion: boolean;
rtl: boolean;
size: number;
sticky: boolean;
tag: null;
};
type ModelTemplate = {
afmt: string;
bafmt: string;
bfont: string;
bqfmt: string;
bsize: number;
did: null;
id: number;
name: string;
ord: number;
qfmt: string;
};
type Model = {
css: string;
did: null;
flds: ModelField[];
id: number;
latexPost: string;
latexPre: string;
latexsvg: boolean;
mod: number;
name: string;
originalStockKind: number;
req: Array<[number, string, number[]]>;
sortf: number;
tmpls: ModelTemplate[];
type: number;
usn: number;
};
type ModelToCreate = {
cardTemplates: Array<{
[key: string]: string;
Back: string;
Front: string;
}>;
css?: string;
inOrderFields: string[];
isCloze?: boolean;
modelName: string;
};
type ModelRequests = Request<'createModel', 6, ModelToCreate, Model> | Request<'findAndReplaceInModels', 6, {
model: {
back: boolean;
css: boolean;
fieldText: string;
front: boolean;
modelName: string;
replaceText: string;
};
}, number> | Request<'findModelsById', 6, {
modelIds: number[];
}, Model[]> | Request<'findModelsByName', 6, {
modelNames: string[];
}, Model[]> | Request<'modelFieldAdd', 6, {
fieldName: string;
index: number;
modelName: string;
}> | Request<'modelFieldDescriptions', 6, {
description: string;
fieldName: string;
modelName: string;
}, boolean> | Request<'modelFieldFonts', 6, {
modelName: string;
}, Record<string, {
font: string;
size: number;
}>> | Request<'modelFieldNames', 6, {
modelName: string;
}, string[]> | Request<'modelFieldRemove', 6, {
fieldName: string;
modelName: string;
}> | Request<'modelFieldRename', 6, {
modelName: string;
newFieldName: string;
oldFieldName: string;
}> | Request<'modelFieldReposition', 6, {
fieldName: string;
index: number;
modelName: string;
}> | Request<'modelFieldSetDescription', 6, {
fieldName: string;
index: number;
modelName: string;
}> | Request<'modelFieldSetFont', 6, {
fieldName: string;
font: string;
modelName: string;
}> | Request<'modelFieldSetFontSize', 6, {
fieldName: string;
fontSize: number;
modelName: string;
}> | Request<'modelFieldsOnTemplates', 6, {
modelName: string;
}, Record<string, [string[], string[]]>> | Request<'modelNames', 6, never, string[]> | Request<'modelNamesAndIds', 6, never, Record<string, number>> | Request<'modelStyling', 6, {
modelName: string;
}, {
css: string;
}> | Request<'modelTemplateAdd', 6, {
modelName: string;
template: {
[key: string]: string;
Back: string;
Front: string;
};
}> | Request<'modelTemplateRemove', 6, {
modelName: string;
templateName: string;
}> | Request<'modelTemplateRename', 6, {
modelName: string;
newTemplateName: string;
oldTemplateName: string;
}> | Request<'modelTemplateReposition', 6, {
index: number;
modelName: string;
templateName: string;
}> | Request<'modelTemplates', 6, {
modelName: string;
}, Record<string, {
[key: string]: string;
Back: string;
Front: string;
}>> | Request<'updateModelStyling', 6, {
model: {
css: string;
name: string;
};
}> | Request<'updateModelTemplates', 6, {
model: {
name: string;
templates: Record<string, {
Back?: string;
Front?: string;
}>;
};
}>; //#endregion
//#region src/types/statistic.d.ts
type ReviewStatisticTuple = [reviewTime: number, cardID: number, usn: number, buttonPressed: number, newInterval: number, previousInterval: number, newFactor: number, reviewDuration: number, reviewType: number];
type StatisticRequests = Request<'cardReviews', 6, {
deck: string;
startID: number;
}, ReviewStatisticTuple[]> | Request<'getCollectionStatsHTML', 6, {
wholeCollection: boolean;
}, string> | Request<'getLatestReviewID', 6, {
deck: string;
}, number> | Request<'getNumCardsReviewedByDay', 6, never, Array<[string, number]>> | Request<'getNumCardsReviewedToday', 6, never, number> | Request<'getReviewsOfCards', 6, {
cards: string[];
}, Record<string, Array<{
/** ButtonPressed */ease: number; /** NewFactor */
factor: number; /** ReviewTime */
id: number; /** NewInterval */
ivl: number; /** PreviousInterval */
lastIvl: number; /** ReviewDuration */
time: number; /** ReviewType */
type: number; /** Usn */
usn: number;
}>>> | Request<'insertReviews', 6, {
reviews: ReviewStatisticTuple[];
}>; //#endregion
//#region src/types/shared.d.ts
/**
* Abstract wrapper over an Anki Connect action / response
*/
type Request<Action extends string, Version extends AnkiConnectVersion, Params = never, Result = null> = {
action: Action;
params: Params;
response: {
error: null | string;
result: Result;
};
version: Version;
};
/**
* Requests
*/
type Requests = CardRequests | DeckRequests | GraphicalRequests | MediaRequests | MiscellaneousRequests | ModelRequests | NoteRequests | StatisticRequests;
type AnkiConnectVersion = 6;
type ParamsForAction<T extends Requests['action']> = Extract<Requests, {
action: T;
}>['params'];
//#endregion
//#region src/types/card.d.ts
type CardBrowserColumns = 'answer' | 'cardDue' | 'cardEase' | 'cardIvl' | 'cardLapses' | 'cardMod' | 'cardReps' | 'deck' | 'note' | 'noteCrt' | 'noteFld' | 'noteMod' | 'noteTags' | 'question' | 'template' | (string & {});
type CardValueKeys = 'data' | 'did' | 'due' | 'factor' | 'flags' | 'id' | 'ivl' | 'lapses' | 'left' | 'mod' | 'odid' | 'odue' | 'ord' | 'queue' | 'reps' | 'type' | 'usn';
type CardInfo = {
answer: string;
buttons?: number[];
cardId: number;
css: string;
deckName: string;
due: number;
fieldOrder: number;
fields: Record<string, {
order: number;
value: string;
}>;
interval: number;
lapses: number;
left: number;
mod: number;
modelName: string;
nextReviews: string[];
note: number;
ord: number;
question: string;
queue: number;
reps: number;
template: string;
type: number;
};
type CardRequests = Request<'answerCards', 6, {
answers: Array<{
cardId: number;
ease: number;
}>;
}, boolean[]> | Request<'areDue', 6, {
cards: number[];
}, boolean[]> | Request<'areSuspended', 6, {
cards: number[];
}, Array<boolean | null>> | Request<'cardsInfo', 6, {
cards: number[];
}, CardInfo[]> | Request<'cardsModTime', 6, {
cards: number[];
}, {
cardId: number;
mod: number;
}> | Request<'cardsToNotes', 6, {
cards: number[];
}, number[]> | Request<'findCards', 6, {
query: string;
}, number[]> | Request<'forgetCards', 6, {
cards: number[];
}> | Request<'getEaseFactors', 6, {
cards: number[];
}, number[]> | Request<'getIntervals', 6, {
cards: number[];
complete?: boolean;
}, number[] | number[][]> | Request<'relearnCards', 6, {
cards: number[];
}> | Request<'setDueDate', 6, {
cards: number[];
days: string;
}, boolean> | Request<'setEaseFactors', 6, {
cards: number[];
easeFactors: number[];
}, boolean[]> | Request<'setSpecificValueOfCard', 6, {
card: number;
keys: CardValueKeys[];
newValues: string[];
}, boolean[]> | Request<'suspend', 6, {
cards: number[];
}, boolean> | Request<'suspended', 6, {
card: number;
}, boolean> | Request<'unsuspend', 6, {
cards: number[];
}, boolean>; //#endregion
//#region src/client.d.ts
/**
* Subset of built-in Fetch interface that's actually used by Anki, for ease of
* external re-implementation when passing a custom fetch function to
* YankiClient.
*/
type YankiFetchAdapter = (input: string, init?: {
body?: string;
headers?: Record<string, string>;
method?: string;
mode?: RequestMode;
}) => Promise<undefined | {
headers: Headers | Record<string, string>;
json(): Promise<any>;
status: number;
}>;
/** Optional options to pass when instantiating a new YankiConnect instance. */
type YankiConnectOptions = {
/**
* Attempt to open the desktop Anki.app if it's not already running.
*
* - `true` will always attempt to open Anki _when a request is made_. This
* might introduce significant latency on the first launch.
* - `false` will never attempt to open Anki. Requests will fail until something
* or someone else opens the Anki app.
* - `immediately` is a special option that will open Anki when the client is
* instantiated.
*
* The Anki desktop app must be running for the client and the underlying
* AnkiConnect service to work.
*
* Currently supported on macOS only.
*
* The client does not attempt to close the app.
*
* @default false
*/
autoLaunch: 'immediately' | boolean;
/**
* Advanced option to customize the resource fetch implementation used to make
* requests to AnkiConnect.
*
* Note that the signature reflects the subset of the built-in Fetch interface
* that's actually used by yanki-connect.
*
* The exact signature of this option is subject to change in the future.
*
* @default fetch
*/
fetchAdapter: undefined | YankiFetchAdapter;
/**
* Host where the AnkiConnect service is running.
*
* @default 'http://127.0.0.1'
*/
host: string;
/**
* AnkiConnect security key (optional)
*
* @default undefined
*/
key: string | undefined;
/**
* Port where the AnkiConnect service is running.
*
* @default 8765
*/
port: number;
/**
* AnkiConnect API version.
*
* Only API version 6 is supported for now.
*
* @default 6
*/
version: AnkiConnectVersion;
};
//#endregion
//#region src/lib/model/model.d.ts
declare const yankiModels: [{
readonly cardTemplates: [{
readonly Back: "{{FrontSide}}\n\n<hr id=answer>\n\n{{Back}}";
readonly Front: "{{Front}}";
readonly YankiNamespace: "{{YankiNamespace}}";
}];
readonly inOrderFields: ["Front", "Back", "YankiNamespace"];
readonly modelName: "Yanki - Basic";
}, {
readonly cardTemplates: [{
readonly Back: "{{cloze:Front}}<br>\n{{Back}}";
readonly Front: "{{cloze:Front}}";
readonly YankiNamespace: "{{YankiNamespace}}";
}];
readonly inOrderFields: ["Front", "Back", "YankiNamespace"];
readonly isCloze: true;
readonly modelName: "Yanki - Cloze";
}, {
readonly cardTemplates: [{
readonly Back: "{{Front}}\n\n<hr id=answer>\n\n{{type:Back}}";
readonly Front: "{{Front}}\n\n{{type:Back}}";
readonly YankiNamespace: "{{YankiNamespace}}";
}];
readonly inOrderFields: ["Front", "Back", "YankiNamespace"];
readonly modelName: "Yanki - Basic (type in the answer)";
}, {
readonly cardTemplates: [{
readonly Back: "{{FrontSide}}\n\n<hr id=answer>\n\n{{Back}}{{#Extra}}\n\n<hr>\n\n{{Extra}}{{/Extra}}";
readonly Front: "{{Front}}";
readonly YankiNamespace: "{{YankiNamespace}}";
}, {
readonly Back: "{{FrontSide}}\n\n<hr id=answer>\n\n{{Front}}{{#Extra}}\n\n<hr>\n\n{{Extra}}{{/Extra}}";
readonly Front: "{{Back}}";
readonly YankiNamespace: "{{YankiNamespace}}";
}];
readonly inOrderFields: ["Front", "Back", "Extra", "YankiNamespace"];
readonly modelName: "Yanki - Basic (and reversed card with extra)";
}];
type YankiModelName = (typeof yankiModels)[number]['modelName'];
//#endregion
//#region src/lib/model/note.d.ts
type YankiNote = Simplify<Omit<ParamsForAction<'addNote'>['note'], 'fields' | 'modelName' | 'options'> & {
cards?: number[];
fields: {
Back: string;
Extra?: string;
Front: string;
YankiNamespace: string;
};
modelName: YankiModelName;
noteId: number | undefined;
}>;
//#endregion
//#region src/lib/shared/types.d.ts
type FetchAdapter = YankiFetchAdapter;
type ManageFilenames = 'off' | 'prompt' | 'response';
type SyncMediaAssets = 'all' | 'local' | 'off' | 'remote';
type FileAdapter = {
readFile(filePath: string): Promise<string>;
readFileBuffer(filePath: string): Promise<Uint8Array>;
rename(oldPath: string, newPath: string): Promise<void>;
stat(filePath: string): Promise<{
ctimeMs: number;
mtimeMs: number;
size: number;
}>;
writeFile(filePath: string, data: string): Promise<void>;
};
type GlobalOptions = {
/**
* Used for wiki link resolution
*/
allFilePaths: string[];
ankiConnectOptions: YankiConnectOptions;
/**
* Automatically sync any changes to AnkiWeb after Yanki has finished syncing
* locally. If false, only local Anki data is updated and you must manually
* invoke a sync to AnkiWeb. This is the equivalent of pushing the "sync"
* button in the Anki app.
*/
ankiWeb: boolean;
/**
* Override where "/" should resolve to... useful in Obsidian to set the vault
* path as the "root"
*/
basePath: string | undefined;
/**
* Run Anki's "Check Database" command after sync updates that might produce
* card corruption
*/
checkDatabase: boolean;
cwd: string;
dryRun: boolean;
/**
* Exposed for Obsidian, currently only used for getting URL content hashes
* and inferring MIME types of URLs without extensions. Note that
* ankiConnectOptions ALSO has a fetch adapter option specifically for
* communicating with AnkiConnect.
*/
fetchAdapter: FetchAdapter | undefined;
fileAdapter: FileAdapter | undefined;
manageFilenames: ManageFilenames;
/**
* Only applies if manageFilenames is `true`. Will _not_ truncate
* user-specified file names in other cases.
*/
maxFilenameLength: number;
namespace: string; /** Ensures that wiki-style links work correctly */
obsidianVault: string | undefined; /** Exposed for testing only */
resolveUrls: boolean;
/**
* Whether to treat single newlines in Markdown as line breaks in the
* resulting HTML (Obsidian has an application-level setting for this)
*/
strictLineBreaks: boolean;
/**
* Only consider exact noteId matches between the local and remote copies to
* be equivalent, don't match local notes with "orphaned" remote notes based
* on content
*/
strictMatching: boolean; /** Sync image, video, and audio assets to Anki's media storage system */
syncMediaAssets: SyncMediaAssets;
};
//#endregion
//#region src/lib/actions/clean.d.ts
type CleanOptions = Pick<GlobalOptions, 'ankiConnectOptions' | 'ankiWeb' | 'dryRun' | 'namespace'>;
declare const defaultC