mirror of
https://github.com/Automattic/harper.git
synced 2025-12-23 08:48:15 +00:00
refactor(core): remove implementation details from public API (#2256)
This commit is contained in:
parent
addb5bf441
commit
43e74ebdf3
30 changed files with 473 additions and 363 deletions
|
|
@ -1,10 +1,11 @@
|
|||
use harper_pos_utils::{BurnChunkerCpu, CachedChunker};
|
||||
use lazy_static::lazy_static;
|
||||
use std::num::NonZero;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub use harper_pos_utils::{BrillChunker, BrillTagger, Chunker, FreqDict, Tagger, UPOS};
|
||||
pub use harper_pos_utils::{
|
||||
BrillChunker, BrillTagger, BurnChunkerCpu, CachedChunker, Chunker, FreqDict, Tagger, UPOS,
|
||||
};
|
||||
|
||||
const BRILL_TAGGER_SOURCE: &str = include_str!("../trained_tagger_model.json");
|
||||
|
||||
|
|
@ -16,6 +17,8 @@ fn uncached_brill_tagger() -> BrillTagger<FreqDict> {
|
|||
serde_json::from_str(BRILL_TAGGER_SOURCE).unwrap()
|
||||
}
|
||||
|
||||
/// Get a copy of a shared, lazily-initialized [`BrillTagger`]. There will be only one instance
|
||||
/// per-process.
|
||||
pub fn brill_tagger() -> Arc<BrillTagger<FreqDict>> {
|
||||
(*BRILL_TAGGER).clone()
|
||||
}
|
||||
|
|
@ -30,6 +33,8 @@ fn uncached_brill_chunker() -> BrillChunker {
|
|||
serde_json::from_str(BRILL_CHUNKER_SOURCE).unwrap()
|
||||
}
|
||||
|
||||
/// Get a copy of a shared, lazily-initialized [`BrillChunker`]. There will be only one instance
|
||||
/// per-process.
|
||||
pub fn brill_chunker() -> Arc<BrillChunker> {
|
||||
(*BRILL_CHUNKER).clone()
|
||||
}
|
||||
|
|
@ -48,6 +53,9 @@ fn uncached_burn_chunker() -> CachedChunker<BurnChunkerCpu> {
|
|||
)
|
||||
}
|
||||
|
||||
/// Get a copy of a shared, lazily-initialized [`BurnChunkerCpu`]. There will be only one instance
|
||||
/// per-process. Since neural net inference is extremely expensive, this chunker is memoized as
|
||||
/// well.
|
||||
pub fn burn_chunker() -> Rc<CachedChunker<BurnChunkerCpu>> {
|
||||
(BURN_CHUNKER).with(|c| c.clone())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ impl Annotation {
|
|||
|
||||
/// Gets an iterator of annotation `Label` from the given document.
|
||||
///
|
||||
/// This is similar to [`self::iter_from_document()`], but this additionally converts
|
||||
/// This is similar to [`Self::iter_from_document`], but this additionally converts
|
||||
/// the [`Annotation`] into [`ariadne::Label`] for convenience.
|
||||
pub(super) fn iter_labels_from_document<'inpt_id>(
|
||||
annotation_type: AnnotationType,
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@ use harper_comments::CommentParser;
|
|||
use harper_core::linting::LintGroup;
|
||||
use harper_core::parsers::{Markdown, MarkdownOptions, OrgMode, PlainEnglish};
|
||||
use harper_core::{
|
||||
CharStringExt, Dialect, DictWordMetadata, Document, Span, TokenKind, TokenStringExt,
|
||||
dict_word_metadata_orthography::OrthFlags,
|
||||
CharStringExt, Dialect, DictWordMetadata, Document, OrthFlags, Span, TokenKind, TokenStringExt,
|
||||
};
|
||||
use harper_ink::InkParser;
|
||||
use harper_literate_haskell::LiterateHaskellParser;
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
mod char_ext;
|
||||
mod char_string;
|
||||
mod currency;
|
||||
pub mod dict_word_metadata;
|
||||
pub mod dict_word_metadata_orthography;
|
||||
mod dict_word_metadata;
|
||||
mod dict_word_metadata_orthography;
|
||||
mod document;
|
||||
mod edit_distance;
|
||||
pub mod expr;
|
||||
|
|
@ -35,8 +35,8 @@ use std::collections::{BTreeMap, VecDeque};
|
|||
pub use char_string::{CharString, CharStringExt};
|
||||
pub use currency::Currency;
|
||||
pub use dict_word_metadata::{
|
||||
AdverbData, ConjunctionData, Degree, DeterminerData, Dialect, DictWordMetadata, NounData,
|
||||
PronounData, VerbData, VerbForm,
|
||||
AdverbData, ConjunctionData, Degree, DeterminerData, Dialect, DialectFlags, DictWordMetadata,
|
||||
NounData, PronounData, VerbData, VerbForm, VerbFormFlags,
|
||||
};
|
||||
pub use dict_word_metadata_orthography::{OrthFlags, Orthography};
|
||||
pub use document::Document;
|
||||
|
|
@ -54,7 +54,7 @@ pub use token_kind::TokenKind;
|
|||
pub use token_string_ext::TokenStringExt;
|
||||
pub use vec_ext::VecExt;
|
||||
|
||||
/// Return harper-core version
|
||||
/// Return `harper-core` version
|
||||
pub fn core_version() -> &'static str {
|
||||
env!("CARGO_PKG_VERSION")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::collections::VecDeque;
|
||||
|
||||
/// Extensions on top of [`Vec`] that make certain common operations easier.
|
||||
pub trait VecExt {
|
||||
/// Removes a list of indices from a Vector.
|
||||
/// Assumes that the provided indices are already in sorted order.
|
||||
|
|
|
|||
|
|
@ -80,10 +80,10 @@
|
|||
//! - All other token kinds are denoted by their variant name.
|
||||
use std::borrow::Cow;
|
||||
|
||||
use harper_core::dict_word_metadata::VerbFormFlags;
|
||||
use harper_core::dict_word_metadata_orthography::OrthFlags;
|
||||
use harper_core::spell::FstDictionary;
|
||||
use harper_core::{Degree, Dialect, DictWordMetadata, Document, TokenKind};
|
||||
use harper_core::{
|
||||
Degree, Dialect, DictWordMetadata, Document, OrthFlags, TokenKind, VerbFormFlags,
|
||||
};
|
||||
|
||||
mod snapshot;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use harper_core::dict_word_metadata::DialectFlags;
|
||||
use harper_core::DialectFlags;
|
||||
use itertools::Itertools;
|
||||
use std::path::Path;
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,11 @@ use crate::{
|
|||
use patch::Patch;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// A [`Chunker`] implementation based on the work by Eric Brill.
|
||||
///
|
||||
/// Additional reading:
|
||||
///
|
||||
/// - [Continuations on Transformation-based Learning](https://elijahpotter.dev/articles/more-transformation-based-learning)
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct BrillChunker {
|
||||
base: UPOSFreqDict,
|
||||
|
|
|
|||
|
|
@ -73,6 +73,9 @@ impl<B: Backend> NpModel<B> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A [`Chunker`] that uses a BiLSTM and the Burn machine learning framework.
|
||||
///
|
||||
/// Additional details in this [talk](https://elijahpotter.dev/articles/i-spoke-at-wordcamp-u.s.-in-2025)
|
||||
pub struct BurnChunker<B: Backend> {
|
||||
vocab: HashMap<String, usize>,
|
||||
model: NpModel<B>,
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ pub use cached_chunker::CachedChunker;
|
|||
pub use upos_freq_dict::UPOSFreqDict;
|
||||
|
||||
/// An implementer of this trait is capable of identifying the noun phrases in a provided sentence.
|
||||
/// [See here](https://en.wikipedia.org/wiki/Shallow_parsing) for more details on what this is and how it can work.
|
||||
pub trait Chunker {
|
||||
/// Iterate over the sentence, identifying the noun phrases contained within.
|
||||
/// A token marked `true` is a component of a noun phrase.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
//! Methods for extracting nominal phrases from datasets.
|
||||
|
||||
use std::collections::VecDeque;
|
||||
|
||||
use hashbrown::HashSet;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,12 @@ use super::error_counter::{ErrorCounter, ErrorKind};
|
|||
|
||||
use crate::{Tagger, UPOS};
|
||||
|
||||
/// A [`Tagger`] implementation based on the work by Eric Brill.
|
||||
///
|
||||
/// Additional reading:
|
||||
///
|
||||
/// - [Brill tagger](https://en.wikipedia.org/wiki/Brill_tagger)
|
||||
/// - [Transformation-based Learning for POS Tagging](https://elijahpotter.dev/articles/transformation-based-learning)
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct BrillTagger<B>
|
||||
where
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ pub use freq_dict::FreqDict;
|
|||
pub use freq_dict_builder::FreqDictBuilder;
|
||||
|
||||
/// An implementer of this trait is capable of assigned Part-of-Speech tags to a provided sentence.
|
||||
/// This is widely useful for various applications. [See here.](https://en.wikipedia.org/wiki/Part-of-speech_tagging)
|
||||
pub trait Tagger {
|
||||
fn tag_sentence(&self, sentence: &[String]) -> Vec<Option<UPOS>>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use std::convert::Into;
|
|||
use std::io::Cursor;
|
||||
use std::sync::Arc;
|
||||
|
||||
use harper_core::dict_word_metadata::DialectFlags;
|
||||
use harper_core::DialectFlags;
|
||||
use harper_core::language_detection::is_doc_likely_english;
|
||||
use harper_core::linting::{LintGroup, Linter as _};
|
||||
use harper_core::parsers::{IsolateEnglish, Markdown, Parser, PlainEnglish};
|
||||
|
|
@ -64,6 +64,7 @@ impl Language {
|
|||
}
|
||||
}
|
||||
|
||||
/// Specifies an English Dialect, often used for linting.
|
||||
#[wasm_bindgen]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
|
||||
pub enum Dialect {
|
||||
|
|
|
|||
|
|
@ -367,7 +367,7 @@ async function setActivationKey(key: ActivationKey) {
|
|||
|
||||
function initializeLinter(dialect: Dialect) {
|
||||
linter = new LocalLinter({
|
||||
binary: new BinaryModule(chrome.runtime.getURL('./wasm/harper_wasm_bg.wasm')),
|
||||
binary: BinaryModule.create(chrome.runtime.getURL('./wasm/harper_wasm_bg.wasm')),
|
||||
dialect,
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
"svelte": "^5.41.0",
|
||||
"svelte-check": "^4.3.3",
|
||||
"tailwindcss": "^4.1.14",
|
||||
"typescript": "^5.9.3",
|
||||
"typescript": "catalog:",
|
||||
"vite": "^7.1.10"
|
||||
},
|
||||
"keywords": [
|
||||
|
|
|
|||
|
|
@ -23,9 +23,10 @@
|
|||
"api:documenter": "api-documenter markdown -i temp"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/api-documenter": "^7.26.10",
|
||||
"@microsoft/api-extractor": "^7.50.1",
|
||||
"@microsoft/api-documenter": "^7.28.1",
|
||||
"@microsoft/api-extractor": "^7.55.1",
|
||||
"@vitest/browser": "^3.0.6",
|
||||
"@vitest/ui": "3.0.8",
|
||||
"harper-wasm": "workspace:*",
|
||||
"marked": "^16.4.1",
|
||||
"p-lazy": "^5.0.0",
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ renderer.link = ({ href, title, text }) => {
|
|||
href = `${href.slice(0, href.length - 3)}.html`;
|
||||
}
|
||||
const titleAttr = title ? ` title="${title}"` : '';
|
||||
return `<a href="${href}" ${titleAttr}>${text}</a>`;
|
||||
return `<a href="${href}" ${titleAttr}>${text.replaceAll('\\_', '_')}</a>`;
|
||||
};
|
||||
|
||||
const markdown = fs.readFileSync(input, 'utf8');
|
||||
|
|
@ -30,7 +30,7 @@ const html = `<!doctype html>
|
|||
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
|
||||
>
|
||||
</head>
|
||||
<body>
|
||||
<body class="container">
|
||||
${body}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -53,13 +53,16 @@ export default interface Linter {
|
|||
/** Get the linting rule descriptions as an object, formatted in Markdown. */
|
||||
getLintDescriptions(): Promise<Record<string, string>>;
|
||||
|
||||
/** Get the linting rule descriptions as a JSON map, formatted in HTML. */
|
||||
/** Get the linting rule descriptions as a JSON map, formatted in HTML.
|
||||
* Wraps the function on the BinaryModule by the same name. */
|
||||
getLintDescriptionsHTMLAsJSON(): Promise<string>;
|
||||
|
||||
/** Get the linting rule descriptions as an object, formatted in HTML */
|
||||
/** Get the linting rule descriptions as an object, formatted in HTML.
|
||||
* Wraps the function on the BinaryModule by the same name. */
|
||||
getLintDescriptionsHTML(): Promise<Record<string, string>>;
|
||||
|
||||
/** Convert a string to Chicago-style title case. */
|
||||
/** Convert a string to Chicago-style title case.
|
||||
Wraps the function on the BinaryModule by the same name. */
|
||||
toTitleCase(text: string): Promise<string>;
|
||||
|
||||
/** Ignore future instances of a lint from a previous linting run in future invocations. */
|
||||
|
|
@ -110,6 +113,7 @@ export default interface Linter {
|
|||
importStatsFile(statsFile: string): Promise<void>;
|
||||
}
|
||||
|
||||
/** The properties and information needed to construct a Linter. */
|
||||
export interface LinterInit {
|
||||
/** The module or path to the WebAssembly binary. */
|
||||
binary: BinaryModule;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,20 @@
|
|||
import type { Dialect, Lint, Suggestion, Linter as WasmLinter } from 'harper-wasm';
|
||||
import { Language } from 'harper-wasm';
|
||||
import LazyPromise from 'p-lazy';
|
||||
import type { BinaryModule } from './binary';
|
||||
import type { SuperBinaryModule } from './binary';
|
||||
import type Linter from './Linter';
|
||||
import type { LinterInit } from './Linter';
|
||||
import type { LintConfig, LintOptions } from './main';
|
||||
|
||||
/** A Linter that runs in the current JavaScript context (meaning it is allowed to block the event loop). */
|
||||
/** A Linter that runs in the current JavaScript context (meaning it is allowed to block the event loop).
|
||||
* See the interface definition for more details. */
|
||||
export default class LocalLinter implements Linter {
|
||||
binary: BinaryModule;
|
||||
binary: SuperBinaryModule;
|
||||
private inner: Promise<WasmLinter>;
|
||||
|
||||
constructor(init: LinterInit) {
|
||||
this.binary = init.binary;
|
||||
this.binary = init.binary as SuperBinaryModule;
|
||||
this.binary.setup();
|
||||
this.inner = this.createInner(init.dialect);
|
||||
}
|
||||
|
||||
|
|
@ -73,11 +75,11 @@ export default class LocalLinter implements Linter {
|
|||
}
|
||||
|
||||
async getDefaultLintConfigAsJSON(): Promise<string> {
|
||||
return this.binary.getDefaultLintConfigAsJSON();
|
||||
return await this.binary.getDefaultLintConfigAsJSON();
|
||||
}
|
||||
|
||||
async getDefaultLintConfig(): Promise<LintConfig> {
|
||||
return this.binary.getDefaultLintConfig();
|
||||
return await this.binary.getDefaultLintConfig();
|
||||
}
|
||||
|
||||
async setLintConfig(config: LintConfig): Promise<void> {
|
||||
|
|
@ -96,7 +98,7 @@ export default class LocalLinter implements Linter {
|
|||
}
|
||||
|
||||
async toTitleCase(text: string): Promise<string> {
|
||||
return this.binary.toTitleCase(text);
|
||||
return await this.binary.toTitleCase(text);
|
||||
}
|
||||
|
||||
async getLintDescriptions(): Promise<Record<string, string>> {
|
||||
|
|
|
|||
84
packages/harper.js/src/Serializer.test.ts
Normal file
84
packages/harper.js/src/Serializer.test.ts
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
import { Span } from 'harper-wasm';
|
||||
import { beforeEach, describe, expect, test } from 'vitest';
|
||||
import { binary } from './binary';
|
||||
import LocalLinter from './LocalLinter';
|
||||
import Serializer from './Serializer';
|
||||
|
||||
describe('Serializer', () => {
|
||||
let serializer = new Serializer(binary);
|
||||
|
||||
beforeEach(() => {
|
||||
serializer = new Serializer(binary);
|
||||
});
|
||||
|
||||
test('works with strings', async () => {
|
||||
const start = 'This is a string';
|
||||
|
||||
const end = await serializer.deserializeArg(
|
||||
structuredClone(await serializer.serializeArg(start)),
|
||||
);
|
||||
|
||||
expect(end).toBe(start);
|
||||
expect(typeof end).toBe(typeof start);
|
||||
});
|
||||
|
||||
test('works with false booleans', async () => {
|
||||
const start = false;
|
||||
|
||||
const end = await serializer.deserializeArg(
|
||||
structuredClone(await serializer.serializeArg(start)),
|
||||
);
|
||||
|
||||
expect(end).toBe(start);
|
||||
expect(typeof end).toBe(typeof start);
|
||||
});
|
||||
|
||||
test('works with true booleans', async () => {
|
||||
const start = true;
|
||||
|
||||
const end = await serializer.deserializeArg(
|
||||
structuredClone(await serializer.serializeArg(start)),
|
||||
);
|
||||
|
||||
expect(end).toBe(start);
|
||||
expect(typeof end).toBe(typeof start);
|
||||
});
|
||||
|
||||
test('works with numbers', async () => {
|
||||
const start = 123;
|
||||
|
||||
const end = await serializer.deserializeArg(
|
||||
structuredClone(await serializer.serializeArg(start)),
|
||||
);
|
||||
|
||||
expect(end).toBe(start);
|
||||
expect(typeof end).toBe(typeof start);
|
||||
});
|
||||
|
||||
test('works with Spans', async () => {
|
||||
const start = Span.new(123, 321);
|
||||
|
||||
const end = await serializer.deserializeArg(
|
||||
structuredClone(await serializer.serializeArg(start)),
|
||||
);
|
||||
|
||||
expect(end.start).toBe(start.start);
|
||||
expect(end.len()).toBe(start.len());
|
||||
expect(typeof end).toBe(typeof start);
|
||||
});
|
||||
|
||||
test('works with Lints', async () => {
|
||||
const linter = new LocalLinter({ binary });
|
||||
const lints = await linter.lint('This is an test.');
|
||||
const start = lints[0];
|
||||
|
||||
expect(start).not.toBeNull();
|
||||
|
||||
const end = await serializer.deserializeArg(
|
||||
structuredClone(await serializer.serializeArg(start)),
|
||||
);
|
||||
|
||||
expect(end.message()).toBe(start.message());
|
||||
expect(end.lint_kind()).toBe(start.lint_kind());
|
||||
});
|
||||
});
|
||||
152
packages/harper.js/src/Serializer.ts
Normal file
152
packages/harper.js/src/Serializer.ts
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
import type { BinaryModule, SuperBinaryModule } from './binary';
|
||||
import { assert } from './utils';
|
||||
|
||||
export type SerializableTypes =
|
||||
| 'string'
|
||||
| 'number'
|
||||
| 'boolean'
|
||||
| 'object'
|
||||
| 'Suggestion'
|
||||
| 'Lint'
|
||||
| 'Span'
|
||||
| 'Array'
|
||||
| 'undefined'
|
||||
| 'bigint';
|
||||
|
||||
/** Serializable argument to a procedure to be run on the web worker. */
|
||||
export interface RequestArg {
|
||||
json: string;
|
||||
type: SerializableTypes;
|
||||
}
|
||||
|
||||
/** An object that is sent to the web worker to request work to be done. */
|
||||
export interface SerializedRequest {
|
||||
/** The procedure to be executed. */
|
||||
procName: string;
|
||||
/** The arguments to the procedure */
|
||||
args: RequestArg[];
|
||||
}
|
||||
|
||||
/** An object that is received by the web worker to request work to be done. */
|
||||
export interface DeserializedRequest {
|
||||
/** The procedure to be executed. */
|
||||
procName: string;
|
||||
/** The arguments to the procedure */
|
||||
args: any[];
|
||||
}
|
||||
|
||||
export function isSerializedRequest(v: unknown): v is SerializedRequest {
|
||||
return typeof v === 'object' && v !== null && 'procName' in v && 'args' in v;
|
||||
}
|
||||
|
||||
/** An internal class that helps the `WorkerLinter` shuffle data across a messaging channel. */
|
||||
export default class Serializer {
|
||||
binary: SuperBinaryModule;
|
||||
|
||||
constructor(binary: BinaryModule) {
|
||||
this.binary = binary as SuperBinaryModule;
|
||||
this.binary.setup();
|
||||
}
|
||||
|
||||
async serializeArg(arg: any): Promise<RequestArg> {
|
||||
const { Lint, Span, Suggestion } = await this.binary.getBinaryModule();
|
||||
|
||||
if (Array.isArray(arg)) {
|
||||
return {
|
||||
json: JSON.stringify(await Promise.all(arg.map((a) => this.serializeArg(a)))),
|
||||
type: 'Array',
|
||||
};
|
||||
}
|
||||
|
||||
const argType = typeof arg;
|
||||
switch (argType) {
|
||||
case 'string':
|
||||
case 'number':
|
||||
case 'boolean':
|
||||
case 'undefined':
|
||||
return { json: JSON.stringify(arg), type: argType };
|
||||
case 'bigint':
|
||||
return { json: arg.toString(), type: argType };
|
||||
}
|
||||
|
||||
if (arg.to_json !== undefined) {
|
||||
const json = arg.to_json();
|
||||
let type: SerializableTypes | undefined;
|
||||
|
||||
if (arg instanceof Lint) {
|
||||
type = 'Lint';
|
||||
} else if (arg instanceof Suggestion) {
|
||||
type = 'Suggestion';
|
||||
} else if (arg instanceof Span) {
|
||||
type = 'Span';
|
||||
}
|
||||
|
||||
if (type === undefined) {
|
||||
throw new Error('Unhandled case: type undefined');
|
||||
}
|
||||
|
||||
return { json, type };
|
||||
}
|
||||
|
||||
if (argType == 'object') {
|
||||
return {
|
||||
json: JSON.stringify(
|
||||
await Promise.all(
|
||||
Object.entries(arg).map(([key, value]) => this.serializeArg([key, value])),
|
||||
),
|
||||
),
|
||||
type: 'object',
|
||||
};
|
||||
}
|
||||
|
||||
throw new Error(`Unhandled case: ${arg}`);
|
||||
}
|
||||
|
||||
async serialize(req: DeserializedRequest): Promise<SerializedRequest> {
|
||||
return {
|
||||
procName: req.procName,
|
||||
args: await Promise.all(req.args.map((arg) => this.serializeArg(arg))),
|
||||
};
|
||||
}
|
||||
|
||||
async deserializeArg(requestArg: RequestArg): Promise<any> {
|
||||
const { Lint, Span, Suggestion } = await this.binary.getBinaryModule();
|
||||
|
||||
switch (requestArg.type) {
|
||||
case 'bigint':
|
||||
return BigInt(requestArg.json);
|
||||
case 'undefined':
|
||||
return undefined;
|
||||
case 'boolean':
|
||||
case 'number':
|
||||
case 'string':
|
||||
return JSON.parse(requestArg.json);
|
||||
case 'Suggestion':
|
||||
return Suggestion.from_json(requestArg.json);
|
||||
case 'Lint':
|
||||
return Lint.from_json(requestArg.json);
|
||||
case 'Span':
|
||||
return Span.from_json(requestArg.json);
|
||||
case 'Array': {
|
||||
const parsed = JSON.parse(requestArg.json);
|
||||
assert(Array.isArray(parsed));
|
||||
return await Promise.all(parsed.map((arg) => this.deserializeArg(arg)));
|
||||
}
|
||||
case 'object': {
|
||||
const parsed = JSON.parse(requestArg.json);
|
||||
return Object.fromEntries(
|
||||
await Promise.all(parsed.map((val: any) => this.deserializeArg(val))),
|
||||
);
|
||||
}
|
||||
default:
|
||||
throw new Error(`Unhandled case: ${requestArg.type}`);
|
||||
}
|
||||
}
|
||||
|
||||
async deserialize(request: SerializedRequest): Promise<DeserializedRequest> {
|
||||
return {
|
||||
procName: request.procName,
|
||||
args: await Promise.all(request.args.map((arg) => this.deserializeArg(arg))),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
/**
|
||||
* Represents the summary of linting results.
|
||||
* Represents the summary of linting results and history.
|
||||
* Useful to show linting statistics or insights to the user.
|
||||
*/
|
||||
export default interface Summary {
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import type { Dialect, Lint, Suggestion } from 'harper-wasm';
|
||||
import type { BinaryModule, DeserializedRequest } from '../binary';
|
||||
import type { BinaryModule } from '../binary';
|
||||
import type Linter from '../Linter';
|
||||
import type { LinterInit } from '../Linter';
|
||||
import type { LintConfig, LintOptions } from '../main';
|
||||
import type { DeserializedRequest } from '../Serializer';
|
||||
import Serializer from '../Serializer';
|
||||
import Worker from './worker.ts?worker&inline';
|
||||
|
||||
/** The data necessary to complete a request once the worker has responded. */
|
||||
|
|
@ -18,6 +20,7 @@ export interface RequestItem {
|
|||
* NOTE: This class will not work properly in Node. In that case, just use `LocalLinter`. */
|
||||
export default class WorkerLinter implements Linter {
|
||||
private binary: BinaryModule;
|
||||
private serializer: Serializer;
|
||||
private dialect?: Dialect;
|
||||
private worker: Worker;
|
||||
private requestQueue: RequestItem[];
|
||||
|
|
@ -25,6 +28,7 @@ export default class WorkerLinter implements Linter {
|
|||
|
||||
constructor(init: LinterInit) {
|
||||
this.binary = init.binary;
|
||||
this.serializer = new Serializer(this.binary);
|
||||
this.dialect = init.dialect;
|
||||
this.worker = new Worker();
|
||||
this.requestQueue = [];
|
||||
|
|
@ -43,7 +47,7 @@ export default class WorkerLinter implements Linter {
|
|||
private setupMainEventListeners() {
|
||||
this.worker.onmessage = (e: MessageEvent) => {
|
||||
const { resolve } = this.requestQueue.shift()!;
|
||||
this.binary.deserializeArg(e.data).then((v) => {
|
||||
this.serializer.deserializeArg(e.data).then((v) => {
|
||||
resolve(v);
|
||||
|
||||
this.working = false;
|
||||
|
|
@ -209,7 +213,7 @@ export default class WorkerLinter implements Linter {
|
|||
|
||||
if (this.requestQueue.length > 0) {
|
||||
const { request } = this.requestQueue[0];
|
||||
const serialized = await this.binary.serialize(request);
|
||||
const serialized = await this.serializer.serialize(request);
|
||||
this.worker.postMessage(serialized);
|
||||
} else {
|
||||
this.working = false;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
/// <reference lib="webworker" />
|
||||
import './shims';
|
||||
import { BinaryModule, isSerializedRequest, type SerializedRequest } from '../binary';
|
||||
import { SuperBinaryModule } from '../binary';
|
||||
import LocalLinter from '../LocalLinter';
|
||||
import Serializer, { isSerializedRequest, type SerializedRequest } from '../Serializer';
|
||||
|
||||
// Notify the main thread that we are ready
|
||||
self.postMessage('ready');
|
||||
|
|
@ -11,16 +12,17 @@ self.onmessage = (e) => {
|
|||
if (typeof binaryUrl !== 'string') {
|
||||
throw new TypeError(`Expected binary to be a string of url but got ${typeof binaryUrl}.`);
|
||||
}
|
||||
const binary = new BinaryModule(binaryUrl);
|
||||
const binary = SuperBinaryModule.create(binaryUrl);
|
||||
const serializer = new Serializer(binary);
|
||||
const linter = new LocalLinter({ binary, dialect });
|
||||
|
||||
async function processRequest(v: SerializedRequest) {
|
||||
const { procName, args } = await binary.deserialize(v);
|
||||
const { procName, args } = await serializer.deserialize(v);
|
||||
|
||||
if (procName in linter) {
|
||||
// @ts-expect-error
|
||||
const res = await linter[procName](...args);
|
||||
postMessage(await binary.serializeArg(res));
|
||||
postMessage(await serializer.serializeArg(res));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,63 +0,0 @@
|
|||
import { Span } from 'harper-wasm';
|
||||
import { expect, test } from 'vitest';
|
||||
import { binary } from './binary';
|
||||
import LocalLinter from './LocalLinter';
|
||||
|
||||
test('works with strings', async () => {
|
||||
const start = 'This is a string';
|
||||
|
||||
const end = await binary.deserializeArg(structuredClone(await binary.serializeArg(start)));
|
||||
|
||||
expect(end).toBe(start);
|
||||
expect(typeof end).toBe(typeof start);
|
||||
});
|
||||
|
||||
test('works with false booleans', async () => {
|
||||
const start = false;
|
||||
|
||||
const end = await binary.deserializeArg(structuredClone(await binary.serializeArg(start)));
|
||||
|
||||
expect(end).toBe(start);
|
||||
expect(typeof end).toBe(typeof start);
|
||||
});
|
||||
|
||||
test('works with true booleans', async () => {
|
||||
const start = true;
|
||||
|
||||
const end = await binary.deserializeArg(structuredClone(await binary.serializeArg(start)));
|
||||
|
||||
expect(end).toBe(start);
|
||||
expect(typeof end).toBe(typeof start);
|
||||
});
|
||||
|
||||
test('works with numbers', async () => {
|
||||
const start = 123;
|
||||
|
||||
const end = await binary.deserializeArg(structuredClone(await binary.serializeArg(start)));
|
||||
|
||||
expect(end).toBe(start);
|
||||
expect(typeof end).toBe(typeof start);
|
||||
});
|
||||
|
||||
test('works with Spans', async () => {
|
||||
const start = Span.new(123, 321);
|
||||
|
||||
const end = await binary.deserializeArg(structuredClone(await binary.serializeArg(start)));
|
||||
|
||||
expect(end.start).toBe(start.start);
|
||||
expect(end.len()).toBe(start.len());
|
||||
expect(typeof end).toBe(typeof start);
|
||||
});
|
||||
|
||||
test('works with Lints', async () => {
|
||||
const linter = new LocalLinter({ binary });
|
||||
const lints = await linter.lint('This is an test.');
|
||||
const start = lints[0];
|
||||
|
||||
expect(start).not.toBeNull();
|
||||
|
||||
const end = await binary.deserializeArg(structuredClone(await binary.serializeArg(start)));
|
||||
|
||||
expect(end.message()).toBe(start.message());
|
||||
expect(end.lint_kind()).toBe(start.lint_kind());
|
||||
});
|
||||
|
|
@ -4,9 +4,8 @@ import { default as binaryUrl } from 'harper-wasm/harper_wasm_bg.wasm?no-inline'
|
|||
import LazyPromise from 'p-lazy';
|
||||
import pMemoize from 'p-memoize';
|
||||
import type { LintConfig } from './main';
|
||||
import { assert } from './utils';
|
||||
|
||||
export const loadBinary = pMemoize(async (binary: string) => {
|
||||
const loadBinary = pMemoize(async (binary: string) => {
|
||||
const exports = await import('harper-wasm');
|
||||
|
||||
let input: InitInput;
|
||||
|
|
@ -26,186 +25,61 @@ export const loadBinary = pMemoize(async (binary: string) => {
|
|||
return exports;
|
||||
});
|
||||
|
||||
export type SerializableTypes =
|
||||
| 'string'
|
||||
| 'number'
|
||||
| 'boolean'
|
||||
| 'object'
|
||||
| 'Suggestion'
|
||||
| 'Lint'
|
||||
| 'Span'
|
||||
| 'Array'
|
||||
| 'undefined'
|
||||
| 'bigint';
|
||||
|
||||
/** Serializable argument to a procedure to be run on the web worker. */
|
||||
export interface RequestArg {
|
||||
json: string;
|
||||
type: SerializableTypes;
|
||||
}
|
||||
|
||||
/** An object that is sent to the web worker to request work to be done. */
|
||||
export interface SerializedRequest {
|
||||
/** The procedure to be executed. */
|
||||
procName: string;
|
||||
/** The arguments to the procedure */
|
||||
args: RequestArg[];
|
||||
}
|
||||
|
||||
/** An object that is received by the web worker to request work to be done. */
|
||||
export interface DeserializedRequest {
|
||||
/** The procedure to be executed. */
|
||||
procName: string;
|
||||
/** The arguments to the procedure */
|
||||
args: any[];
|
||||
}
|
||||
|
||||
export function isSerializedRequest(v: unknown): v is SerializedRequest {
|
||||
return typeof v === 'object' && v !== null && 'procName' in v && 'args' in v;
|
||||
}
|
||||
|
||||
/** This class aims to define the communication protocol between the main thread and the worker.
|
||||
* Note that much of the complication here comes from the fact that we can't serialize function calls or referenced WebAssembly memory.*/
|
||||
/** A wrapper around the underlying WebAssembly module that contains Harper's core code. Used to construct a `Linter`, as well as access some miscellaneous other functions. */
|
||||
export class BinaryModule {
|
||||
public url: string | URL;
|
||||
public url: string | URL = '';
|
||||
private inner: Promise<typeof import('harper-wasm')> | null = null;
|
||||
|
||||
private inner: Promise<typeof import('harper-wasm')>;
|
||||
/** Load a binary from a specified URL. This is the only recommended way to construct this type. */
|
||||
public static create(url: string | URL): BinaryModule {
|
||||
const module = new SuperBinaryModule();
|
||||
|
||||
constructor(url: string | URL) {
|
||||
this.url = url;
|
||||
this.inner = LazyPromise.from(() =>
|
||||
loadBinary(typeof this.url === 'string' ? this.url : this.url.href),
|
||||
module.url = url;
|
||||
module.inner = LazyPromise.from(() =>
|
||||
loadBinary(typeof module.url === 'string' ? module.url : module.url.href),
|
||||
);
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
async getDefaultLintConfigAsJSON(): Promise<string> {
|
||||
const exported = await this.inner;
|
||||
public async getDefaultLintConfigAsJSON(): Promise<string> {
|
||||
const exported = await this.inner!;
|
||||
return exported.get_default_lint_config_as_json();
|
||||
}
|
||||
|
||||
async getDefaultLintConfig(): Promise<LintConfig> {
|
||||
const exported = await this.inner;
|
||||
public async getDefaultLintConfig(): Promise<LintConfig> {
|
||||
const exported = await this.inner!;
|
||||
return exported.get_default_lint_config();
|
||||
}
|
||||
|
||||
async toTitleCase(text: string): Promise<string> {
|
||||
const exported = await this.inner;
|
||||
public async toTitleCase(text: string): Promise<string> {
|
||||
const exported = await this.inner!;
|
||||
return exported.to_title_case(text);
|
||||
}
|
||||
|
||||
async setup(): Promise<void> {
|
||||
const exported = await this.inner;
|
||||
public async setup(): Promise<void> {
|
||||
const exported = await this.inner!;
|
||||
exported.setup();
|
||||
}
|
||||
|
||||
async createLinter(dialect?: Dialect): Promise<WasmLinter> {
|
||||
const exported = await this.inner;
|
||||
return exported.Linter.new(dialect ?? Dialect.American);
|
||||
}
|
||||
|
||||
async serializeArg(arg: any): Promise<RequestArg> {
|
||||
const { Lint, Span, Suggestion } = await this.inner;
|
||||
|
||||
if (Array.isArray(arg)) {
|
||||
return {
|
||||
json: JSON.stringify(await Promise.all(arg.map((a) => this.serializeArg(a)))),
|
||||
type: 'Array',
|
||||
};
|
||||
}
|
||||
|
||||
const argType = typeof arg;
|
||||
switch (argType) {
|
||||
case 'string':
|
||||
case 'number':
|
||||
case 'boolean':
|
||||
case 'undefined':
|
||||
return { json: JSON.stringify(arg), type: argType };
|
||||
case 'bigint':
|
||||
return { json: arg.toString(), type: argType };
|
||||
}
|
||||
|
||||
if (arg.to_json !== undefined) {
|
||||
const json = arg.to_json();
|
||||
let type: SerializableTypes | undefined;
|
||||
|
||||
if (arg instanceof Lint) {
|
||||
type = 'Lint';
|
||||
} else if (arg instanceof Suggestion) {
|
||||
type = 'Suggestion';
|
||||
} else if (arg instanceof Span) {
|
||||
type = 'Span';
|
||||
}
|
||||
|
||||
if (type === undefined) {
|
||||
throw new Error('Unhandled case: type undefined');
|
||||
}
|
||||
|
||||
return { json, type };
|
||||
}
|
||||
|
||||
if (argType == 'object') {
|
||||
return {
|
||||
json: JSON.stringify(
|
||||
await Promise.all(
|
||||
Object.entries(arg).map(([key, value]) => this.serializeArg([key, value])),
|
||||
),
|
||||
),
|
||||
type: 'object',
|
||||
};
|
||||
}
|
||||
|
||||
throw new Error(`Unhandled case: ${arg}`);
|
||||
}
|
||||
|
||||
async serialize(req: DeserializedRequest): Promise<SerializedRequest> {
|
||||
return {
|
||||
procName: req.procName,
|
||||
args: await Promise.all(req.args.map((arg) => this.serializeArg(arg))),
|
||||
};
|
||||
}
|
||||
|
||||
async deserializeArg(requestArg: RequestArg): Promise<any> {
|
||||
const { Lint, Span, Suggestion } = await this.inner;
|
||||
|
||||
switch (requestArg.type) {
|
||||
case 'bigint':
|
||||
return BigInt(requestArg.json);
|
||||
case 'undefined':
|
||||
return undefined;
|
||||
case 'boolean':
|
||||
case 'number':
|
||||
case 'string':
|
||||
return JSON.parse(requestArg.json);
|
||||
case 'Suggestion':
|
||||
return Suggestion.from_json(requestArg.json);
|
||||
case 'Lint':
|
||||
return Lint.from_json(requestArg.json);
|
||||
case 'Span':
|
||||
return Span.from_json(requestArg.json);
|
||||
case 'Array': {
|
||||
const parsed = JSON.parse(requestArg.json);
|
||||
assert(Array.isArray(parsed));
|
||||
return await Promise.all(parsed.map((arg) => this.deserializeArg(arg)));
|
||||
}
|
||||
case 'object': {
|
||||
const parsed = JSON.parse(requestArg.json);
|
||||
return Object.fromEntries(
|
||||
await Promise.all(parsed.map((val: any) => this.deserializeArg(val))),
|
||||
);
|
||||
}
|
||||
default:
|
||||
throw new Error(`Unhandled case: ${requestArg.type}`);
|
||||
}
|
||||
}
|
||||
|
||||
async deserialize(request: SerializedRequest): Promise<DeserializedRequest> {
|
||||
return {
|
||||
procName: request.procName,
|
||||
args: await Promise.all(request.args.map((arg) => this.deserializeArg(arg))),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const binary = /*@__PURE__*/ new BinaryModule(binaryUrl);
|
||||
export class SuperBinaryModule extends BinaryModule {
|
||||
async createLinter(dialect?: Dialect): Promise<WasmLinter> {
|
||||
const exported = await this.getBinaryModule();
|
||||
return exported.Linter.new(dialect ?? Dialect.American);
|
||||
}
|
||||
|
||||
export const binaryInlined = /*@__PURE__*/ new BinaryModule(binaryInlinedUrl);
|
||||
async getBinaryModule(): Promise<any> {
|
||||
return await LazyPromise.from(() =>
|
||||
loadBinary(typeof this.url === 'string' ? this.url : this.url.href),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** A version of the Harper WebAssembly binary stored inline as a data URL.
|
||||
* Can be tree-shaken if unused. */
|
||||
export const binary = /*@__PURE__*/ BinaryModule.create(binaryUrl);
|
||||
|
||||
/** A version of the Harper WebAssembly binary stored inline as a data URL.
|
||||
* Can be tree-shaken if unused. */
|
||||
export const binaryInlined = /*@__PURE__*/ BinaryModule.create(binaryInlinedUrl);
|
||||
|
|
|
|||
|
|
@ -4,11 +4,6 @@ export {
|
|||
BinaryModule,
|
||||
binary,
|
||||
binaryInlined,
|
||||
type DeserializedRequest,
|
||||
isSerializedRequest,
|
||||
type RequestArg,
|
||||
type SerializableTypes,
|
||||
type SerializedRequest,
|
||||
} from './binary';
|
||||
export type { default as Linter, LinterInit } from './Linter';
|
||||
export { default as LocalLinter } from './LocalLinter';
|
||||
|
|
@ -18,7 +13,7 @@ export { default as WorkerLinter } from './WorkerLinter';
|
|||
* This is a record, since you shouldn't hard-code the existence of any particular rules and should generalize based on this struct. */
|
||||
export type LintConfig = Record<string, boolean | null>;
|
||||
|
||||
/** The option used to configure the parser for an individual linting operation. */
|
||||
/** Options available to configure Harper's parser for an individual linting operation. */
|
||||
export interface LintOptions {
|
||||
/** The markup language that is being passed. Defaults to `markdown`. */
|
||||
language?: 'plaintext' | 'markdown';
|
||||
|
|
|
|||
191
pnpm-lock.yaml
generated
191
pnpm-lock.yaml
generated
|
|
@ -16,7 +16,7 @@ catalogs:
|
|||
specifier: ^2.8.1
|
||||
version: 2.8.1
|
||||
typescript:
|
||||
specifier: ^5.8.2
|
||||
specifier: ^5.9.3
|
||||
version: 5.9.3
|
||||
|
||||
importers:
|
||||
|
|
@ -169,7 +169,7 @@ importers:
|
|||
specifier: ^4.1.14
|
||||
version: 4.1.17
|
||||
typescript:
|
||||
specifier: ^5.9.3
|
||||
specifier: 'catalog:'
|
||||
version: 5.9.3
|
||||
vite:
|
||||
specifier: ^7.1.10
|
||||
|
|
@ -178,14 +178,17 @@ importers:
|
|||
packages/harper.js:
|
||||
devDependencies:
|
||||
'@microsoft/api-documenter':
|
||||
specifier: ^7.26.10
|
||||
version: 7.26.17(@types/node@22.13.10)
|
||||
specifier: ^7.28.1
|
||||
version: 7.28.1(@types/node@22.13.10)
|
||||
'@microsoft/api-extractor':
|
||||
specifier: ^7.50.1
|
||||
version: 7.52.1(@types/node@22.13.10)
|
||||
specifier: ^7.55.1
|
||||
version: 7.55.1(@types/node@22.13.10)
|
||||
'@vitest/browser':
|
||||
specifier: ^3.0.6
|
||||
version: 3.0.8(@testing-library/dom@10.4.0)(@types/node@22.13.10)(playwright@1.52.0)(typescript@5.9.3)(vite@6.3.5(@types/node@22.13.10)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.7.0))(vitest@3.0.8)
|
||||
'@vitest/ui':
|
||||
specifier: 3.0.8
|
||||
version: 3.0.8(vitest@3.0.8)
|
||||
harper-wasm:
|
||||
specifier: workspace:*
|
||||
version: link:../../harper-wasm/pkg
|
||||
|
|
@ -218,7 +221,7 @@ importers:
|
|||
version: 0.3.0(vite@6.3.5(@types/node@22.13.10)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.7.0))
|
||||
vitest:
|
||||
specifier: ^3.0.5
|
||||
version: 3.0.8(@types/debug@4.1.12)(@types/node@22.13.10)(@vitest/browser@3.0.8)(jiti@2.6.1)(jsdom@20.0.3)(lightningcss@1.30.2)(msw@2.7.3(@types/node@22.13.10)(typescript@5.9.3))(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.7.0)
|
||||
version: 3.0.8(@types/debug@4.1.12)(@types/node@22.13.10)(@vitest/browser@3.0.8)(@vitest/ui@3.0.8)(jiti@2.6.1)(jsdom@20.0.3)(lightningcss@1.30.2)(msw@2.7.3(@types/node@22.13.10)(typescript@5.9.3))(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.7.0)
|
||||
|
||||
packages/harper.js/examples/commonjs-simple:
|
||||
dependencies:
|
||||
|
|
@ -340,7 +343,7 @@ importers:
|
|||
version: 6.3.5(@types/node@22.13.10)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.7.0)
|
||||
vitest:
|
||||
specifier: ^3.0.8
|
||||
version: 3.0.8(@types/debug@4.1.12)(@types/node@22.13.10)(@vitest/browser@3.0.8)(jiti@2.6.1)(jsdom@20.0.3)(lightningcss@1.30.2)(msw@2.7.3(@types/node@22.13.10)(typescript@5.9.3))(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.7.0)
|
||||
version: 3.0.8(@types/debug@4.1.12)(@types/node@22.13.10)(@vitest/browser@3.0.8)(@vitest/ui@3.0.8)(jiti@2.6.1)(jsdom@20.0.3)(lightningcss@1.30.2)(msw@2.7.3(@types/node@22.13.10)(typescript@5.9.3))(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.7.0)
|
||||
|
||||
packages/vscode-plugin:
|
||||
dependencies:
|
||||
|
|
@ -2603,22 +2606,22 @@ packages:
|
|||
'@marijn/find-cluster-break@1.0.2':
|
||||
resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==}
|
||||
|
||||
'@microsoft/api-documenter@7.26.17':
|
||||
resolution: {integrity: sha512-LOS9U6EJVpejN0vNXFBPdbRW9D2bPJI8FYfLGSaEeiqPfMBlH5QYLKt+OaJomx72uj9Ei6/W49mftK/c+UGPjg==}
|
||||
'@microsoft/api-documenter@7.28.1':
|
||||
resolution: {integrity: sha512-mkAss5DhyKtjQ9n+KURxOjz769WhTE376L9D0e6cX/98GBq1fv4SD6AVIOOFxYIsQv+NivskjUhsa+Geq7T2tQ==}
|
||||
hasBin: true
|
||||
|
||||
'@microsoft/api-extractor-model@7.30.4':
|
||||
resolution: {integrity: sha512-RobC0gyVYsd2Fao9MTKOfTdBm41P/bCMUmzS5mQ7/MoAKEqy0FOBph3JOYdq4X4BsEnMEiSHc+0NUNmdzxCpjA==}
|
||||
'@microsoft/api-extractor-model@7.32.1':
|
||||
resolution: {integrity: sha512-u4yJytMYiUAnhcNQcZDTh/tVtlrzKlyKrQnLOV+4Qr/5gV+cpufWzCYAB1Q23URFqD6z2RoL2UYncM9xJVGNKA==}
|
||||
|
||||
'@microsoft/api-extractor@7.52.1':
|
||||
resolution: {integrity: sha512-m3I5uAwE05orsu3D1AGyisX5KxsgVXB+U4bWOOaX/Z7Ftp/2Cy41qsNhO6LPvSxHBaapyser5dVorF1t5M6tig==}
|
||||
'@microsoft/api-extractor@7.55.1':
|
||||
resolution: {integrity: sha512-l8Z+8qrLkZFM3HM95Dbpqs6G39fpCa7O5p8A7AkA6hSevxkgwsOlLrEuPv0ADOyj5dI1Af5WVDiwpKG/ya5G3w==}
|
||||
hasBin: true
|
||||
|
||||
'@microsoft/tsdoc-config@0.17.1':
|
||||
resolution: {integrity: sha512-UtjIFe0C6oYgTnad4q1QP4qXwLhe6tIpNTRStJ2RZEPIkqQPREAwE5spzVxsdn9UaEMUqhh0AqSx3X4nWAKXWw==}
|
||||
'@microsoft/tsdoc-config@0.18.0':
|
||||
resolution: {integrity: sha512-8N/vClYyfOH+l4fLkkr9+myAoR6M7akc8ntBJ4DJdWH2b09uVfr71+LTMpNyG19fNqWDg8KEDZhx5wxuqHyGjw==}
|
||||
|
||||
'@microsoft/tsdoc@0.15.1':
|
||||
resolution: {integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==}
|
||||
'@microsoft/tsdoc@0.16.0':
|
||||
resolution: {integrity: sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==}
|
||||
|
||||
'@mswjs/interceptors@0.37.6':
|
||||
resolution: {integrity: sha512-wK+5pLK5XFmgtH3aQ2YVvA3HohS3xqV/OxuVOdNx9Wpnz7VE/fnC+e1A7ln6LFYeck7gOJ/dsZV6OLplOtAJ2w==}
|
||||
|
|
@ -3307,27 +3310,35 @@ packages:
|
|||
'@rtsao/scc@1.1.0':
|
||||
resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
|
||||
|
||||
'@rushstack/node-core-library@5.12.0':
|
||||
resolution: {integrity: sha512-QSwwzgzWoil1SCQse+yCHwlhRxNv2dX9siPnAb9zR/UmMhac4mjMrlMZpk64BlCeOFi1kJKgXRkihSwRMbboAQ==}
|
||||
'@rushstack/node-core-library@5.19.0':
|
||||
resolution: {integrity: sha512-BxAopbeWBvNJ6VGiUL+5lbJXywTdsnMeOS8j57Cn/xY10r6sV/gbsTlfYKjzVCUBZATX2eRzJHSMCchsMTGN6A==}
|
||||
peerDependencies:
|
||||
'@types/node': '*'
|
||||
peerDependenciesMeta:
|
||||
'@types/node':
|
||||
optional: true
|
||||
|
||||
'@rushstack/rig-package@0.5.3':
|
||||
resolution: {integrity: sha512-olzSSjYrvCNxUFZowevC3uz8gvKr3WTpHQ7BkpjtRpA3wK+T0ybep/SRUMfr195gBzJm5gaXw0ZMgjIyHqJUow==}
|
||||
|
||||
'@rushstack/terminal@0.15.1':
|
||||
resolution: {integrity: sha512-3vgJYwumcjoDOXU3IxZfd616lqOdmr8Ezj4OWgJZfhmiBK4Nh7eWcv8sU8N/HdzXcuHDXCRGn/6O2Q75QvaZMA==}
|
||||
'@rushstack/problem-matcher@0.1.1':
|
||||
resolution: {integrity: sha512-Fm5XtS7+G8HLcJHCWpES5VmeMyjAKaWeyZU5qPzZC+22mPlJzAsOxymHiWIfuirtPckX3aptWws+K2d0BzniJA==}
|
||||
peerDependencies:
|
||||
'@types/node': '*'
|
||||
peerDependenciesMeta:
|
||||
'@types/node':
|
||||
optional: true
|
||||
|
||||
'@rushstack/ts-command-line@4.23.6':
|
||||
resolution: {integrity: sha512-7WepygaF3YPEoToh4MAL/mmHkiIImQq3/uAkQX46kVoKTNOOlCtFGyNnze6OYuWw2o9rxsyrHVfIBKxq/am2RA==}
|
||||
'@rushstack/rig-package@0.6.0':
|
||||
resolution: {integrity: sha512-ZQmfzsLE2+Y91GF15c65L/slMRVhF6Hycq04D4TwtdGaUAbIXXg9c5pKA5KFU7M4QMaihoobp9JJYpYcaY3zOw==}
|
||||
|
||||
'@rushstack/terminal@0.19.4':
|
||||
resolution: {integrity: sha512-f4XQk02CrKfrMgyOfhYd3qWI944dLC21S4I/LUhrlAP23GTMDNG6EK5effQtFkISwUKCgD9vMBrJZaPSUquxWQ==}
|
||||
peerDependencies:
|
||||
'@types/node': '*'
|
||||
peerDependenciesMeta:
|
||||
'@types/node':
|
||||
optional: true
|
||||
|
||||
'@rushstack/ts-command-line@5.1.4':
|
||||
resolution: {integrity: sha512-H0I6VdJ6sOUbktDFpP2VW5N29w8v4hRoNZOQz02vtEi6ZTYL1Ju8u+TcFiFawUDrUsx/5MQTUhd79uwZZVwVlA==}
|
||||
|
||||
'@sec-ant/readable-stream@0.4.1':
|
||||
resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==}
|
||||
|
|
@ -4321,6 +4332,11 @@ packages:
|
|||
'@vitest/spy@3.0.8':
|
||||
resolution: {integrity: sha512-MR+PzJa+22vFKYb934CejhR4BeRpMSoxkvNoDit68GQxRLSf11aT6CTj3XaqUU9rxgWJFnqicN/wxw6yBRkI1Q==}
|
||||
|
||||
'@vitest/ui@3.0.8':
|
||||
resolution: {integrity: sha512-MfTjaLU+Gw/lYorgwFZ06Cym+Mj9hPfZh/Q91d4JxyAHiicAakPTvS7zYCSHF+5cErwu2PVBe1alSjuh6L/UiA==}
|
||||
peerDependencies:
|
||||
vitest: 3.0.8
|
||||
|
||||
'@vitest/utils@3.0.8':
|
||||
resolution: {integrity: sha512-nkBC3aEhfX2PdtQI/QwAWp8qZWwzASsU4Npbcd5RdMPBSSLCpkZp52P3xku3s3uA0HIEhGvEcF8rNkBsz9dQ4Q==}
|
||||
|
||||
|
|
@ -6178,6 +6194,10 @@ packages:
|
|||
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
|
||||
engines: {node: '>=0.3.1'}
|
||||
|
||||
diff@8.0.2:
|
||||
resolution: {integrity: sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==}
|
||||
engines: {node: '>=0.3.1'}
|
||||
|
||||
dir-glob@3.0.1:
|
||||
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
|
||||
engines: {node: '>=8'}
|
||||
|
|
@ -6867,6 +6887,9 @@ packages:
|
|||
fflate@0.4.8:
|
||||
resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==}
|
||||
|
||||
fflate@0.8.2:
|
||||
resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
|
||||
|
||||
file-entry-cache@10.0.7:
|
||||
resolution: {integrity: sha512-txsf5fu3anp2ff3+gOJJzRImtrtm/oa9tYLN0iTuINZ++EyVR/nRrg2fKYwvG/pXDofcrvvb0scEbX3NyW/COw==}
|
||||
|
||||
|
|
@ -8165,10 +8188,6 @@ packages:
|
|||
js-tokens@4.0.0:
|
||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||
|
||||
js-yaml@3.13.1:
|
||||
resolution: {integrity: sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==}
|
||||
hasBin: true
|
||||
|
||||
js-yaml@3.14.1:
|
||||
resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
|
||||
hasBin: true
|
||||
|
|
@ -11115,8 +11134,8 @@ packages:
|
|||
third-party-web@0.26.5:
|
||||
resolution: {integrity: sha512-tDuKQJUTfjvi9Fcrs1s6YAQAB9mzhTSbBZMfNgtWNmJlHuoFeXO6dzBFdGeCWRvYL50jQGK0jPsBZYxqZQJ2SA==}
|
||||
|
||||
third-party-web@0.28.0:
|
||||
resolution: {integrity: sha512-4P798O67JmIKRJfJ1HSOkIsZrx2+FuaN2jTQX+imHXFPbGp17KSMDabYxrRT011B3gBzaoHFhUkBlEkNZN8vuQ==}
|
||||
third-party-web@0.29.0:
|
||||
resolution: {integrity: sha512-nBDSJw5B7Sl1YfsATG2XkW5qgUPODbJhXw++BKygi9w6O/NKS98/uY/nR/DxDq2axEjL6halHW1v+jhm/j1DBQ==}
|
||||
|
||||
through@2.3.8:
|
||||
resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
|
||||
|
|
@ -11133,10 +11152,6 @@ packages:
|
|||
tinyexec@0.3.2:
|
||||
resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
|
||||
|
||||
tinyglobby@0.2.12:
|
||||
resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
tinyglobby@0.2.13:
|
||||
resolution: {integrity: sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
|
@ -15054,37 +15069,38 @@ snapshots:
|
|||
|
||||
'@marijn/find-cluster-break@1.0.2': {}
|
||||
|
||||
'@microsoft/api-documenter@7.26.17(@types/node@22.13.10)':
|
||||
'@microsoft/api-documenter@7.28.1(@types/node@22.13.10)':
|
||||
dependencies:
|
||||
'@microsoft/api-extractor-model': 7.30.4(@types/node@22.13.10)
|
||||
'@microsoft/tsdoc': 0.15.1
|
||||
'@rushstack/node-core-library': 5.12.0(@types/node@22.13.10)
|
||||
'@rushstack/terminal': 0.15.1(@types/node@22.13.10)
|
||||
'@rushstack/ts-command-line': 4.23.6(@types/node@22.13.10)
|
||||
js-yaml: 3.13.1
|
||||
'@microsoft/api-extractor-model': 7.32.1(@types/node@22.13.10)
|
||||
'@microsoft/tsdoc': 0.16.0
|
||||
'@rushstack/node-core-library': 5.19.0(@types/node@22.13.10)
|
||||
'@rushstack/terminal': 0.19.4(@types/node@22.13.10)
|
||||
'@rushstack/ts-command-line': 5.1.4(@types/node@22.13.10)
|
||||
js-yaml: 4.1.0
|
||||
resolve: 1.22.10
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
|
||||
'@microsoft/api-extractor-model@7.30.4(@types/node@22.13.10)':
|
||||
'@microsoft/api-extractor-model@7.32.1(@types/node@22.13.10)':
|
||||
dependencies:
|
||||
'@microsoft/tsdoc': 0.15.1
|
||||
'@microsoft/tsdoc-config': 0.17.1
|
||||
'@rushstack/node-core-library': 5.12.0(@types/node@22.13.10)
|
||||
'@microsoft/tsdoc': 0.16.0
|
||||
'@microsoft/tsdoc-config': 0.18.0
|
||||
'@rushstack/node-core-library': 5.19.0(@types/node@22.13.10)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
|
||||
'@microsoft/api-extractor@7.52.1(@types/node@22.13.10)':
|
||||
'@microsoft/api-extractor@7.55.1(@types/node@22.13.10)':
|
||||
dependencies:
|
||||
'@microsoft/api-extractor-model': 7.30.4(@types/node@22.13.10)
|
||||
'@microsoft/tsdoc': 0.15.1
|
||||
'@microsoft/tsdoc-config': 0.17.1
|
||||
'@rushstack/node-core-library': 5.12.0(@types/node@22.13.10)
|
||||
'@rushstack/rig-package': 0.5.3
|
||||
'@rushstack/terminal': 0.15.1(@types/node@22.13.10)
|
||||
'@rushstack/ts-command-line': 4.23.6(@types/node@22.13.10)
|
||||
'@microsoft/api-extractor-model': 7.32.1(@types/node@22.13.10)
|
||||
'@microsoft/tsdoc': 0.16.0
|
||||
'@microsoft/tsdoc-config': 0.18.0
|
||||
'@rushstack/node-core-library': 5.19.0(@types/node@22.13.10)
|
||||
'@rushstack/rig-package': 0.6.0
|
||||
'@rushstack/terminal': 0.19.4(@types/node@22.13.10)
|
||||
'@rushstack/ts-command-line': 5.1.4(@types/node@22.13.10)
|
||||
diff: 8.0.2
|
||||
lodash: 4.17.21
|
||||
minimatch: 3.0.8
|
||||
minimatch: 10.0.3
|
||||
resolve: 1.22.10
|
||||
semver: 7.5.4
|
||||
source-map: 0.6.1
|
||||
|
|
@ -15092,14 +15108,14 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
|
||||
'@microsoft/tsdoc-config@0.17.1':
|
||||
'@microsoft/tsdoc-config@0.18.0':
|
||||
dependencies:
|
||||
'@microsoft/tsdoc': 0.15.1
|
||||
'@microsoft/tsdoc': 0.16.0
|
||||
ajv: 8.12.0
|
||||
jju: 1.4.0
|
||||
resolve: 1.22.10
|
||||
|
||||
'@microsoft/tsdoc@0.15.1': {}
|
||||
'@microsoft/tsdoc@0.16.0': {}
|
||||
|
||||
'@mswjs/interceptors@0.37.6':
|
||||
dependencies:
|
||||
|
|
@ -15200,7 +15216,7 @@ snapshots:
|
|||
|
||||
'@paulirish/trace_engine@0.0.44':
|
||||
dependencies:
|
||||
third-party-web: 0.28.0
|
||||
third-party-web: 0.29.0
|
||||
|
||||
'@php-wasm/node-polyfills@0.6.16': {}
|
||||
|
||||
|
|
@ -15712,7 +15728,7 @@ snapshots:
|
|||
|
||||
'@rtsao/scc@1.1.0': {}
|
||||
|
||||
'@rushstack/node-core-library@5.12.0(@types/node@22.13.10)':
|
||||
'@rushstack/node-core-library@5.19.0(@types/node@22.13.10)':
|
||||
dependencies:
|
||||
ajv: 8.13.0
|
||||
ajv-draft-04: 1.0.0(ajv@8.13.0)
|
||||
|
|
@ -15725,21 +15741,26 @@ snapshots:
|
|||
optionalDependencies:
|
||||
'@types/node': 22.13.10
|
||||
|
||||
'@rushstack/rig-package@0.5.3':
|
||||
'@rushstack/problem-matcher@0.1.1(@types/node@22.13.10)':
|
||||
optionalDependencies:
|
||||
'@types/node': 22.13.10
|
||||
|
||||
'@rushstack/rig-package@0.6.0':
|
||||
dependencies:
|
||||
resolve: 1.22.10
|
||||
strip-json-comments: 3.1.1
|
||||
|
||||
'@rushstack/terminal@0.15.1(@types/node@22.13.10)':
|
||||
'@rushstack/terminal@0.19.4(@types/node@22.13.10)':
|
||||
dependencies:
|
||||
'@rushstack/node-core-library': 5.12.0(@types/node@22.13.10)
|
||||
'@rushstack/node-core-library': 5.19.0(@types/node@22.13.10)
|
||||
'@rushstack/problem-matcher': 0.1.1(@types/node@22.13.10)
|
||||
supports-color: 8.1.1
|
||||
optionalDependencies:
|
||||
'@types/node': 22.13.10
|
||||
|
||||
'@rushstack/ts-command-line@4.23.6(@types/node@22.13.10)':
|
||||
'@rushstack/ts-command-line@5.1.4(@types/node@22.13.10)':
|
||||
dependencies:
|
||||
'@rushstack/terminal': 0.15.1(@types/node@22.13.10)
|
||||
'@rushstack/terminal': 0.19.4(@types/node@22.13.10)
|
||||
'@types/argparse': 1.0.38
|
||||
argparse: 1.0.10
|
||||
string-argv: 0.3.2
|
||||
|
|
@ -16963,7 +16984,7 @@ snapshots:
|
|||
dependencies:
|
||||
'@sveltejs/kit': 2.48.5(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.43.12)(vite@6.3.5(@types/node@22.13.10)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.7.0)))(svelte@5.43.12)(vite@6.3.5(@types/node@22.13.10)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.7.0))
|
||||
kolorist: 1.8.0
|
||||
tinyglobby: 0.2.12
|
||||
tinyglobby: 0.2.15
|
||||
vite-plugin-pwa: 0.21.1(vite@6.3.5(@types/node@22.13.10)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.7.0))(workbox-build@7.3.0(@types/babel__core@7.20.5))(workbox-window@7.3.0)
|
||||
|
||||
'@vitest/browser@3.0.8(@testing-library/dom@10.4.0)(@types/node@22.13.10)(playwright@1.52.0)(typescript@5.9.3)(vite@6.3.5(@types/node@22.13.10)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.7.0))(vitest@3.0.8)':
|
||||
|
|
@ -16975,7 +16996,7 @@ snapshots:
|
|||
msw: 2.7.3(@types/node@22.13.10)(typescript@5.9.3)
|
||||
sirv: 3.0.1
|
||||
tinyrainbow: 2.0.0
|
||||
vitest: 3.0.8(@types/debug@4.1.12)(@types/node@22.13.10)(@vitest/browser@3.0.8)(jiti@2.6.1)(jsdom@20.0.3)(lightningcss@1.30.2)(msw@2.7.3(@types/node@22.13.10)(typescript@5.9.3))(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.7.0)
|
||||
vitest: 3.0.8(@types/debug@4.1.12)(@types/node@22.13.10)(@vitest/browser@3.0.8)(@vitest/ui@3.0.8)(jiti@2.6.1)(jsdom@20.0.3)(lightningcss@1.30.2)(msw@2.7.3(@types/node@22.13.10)(typescript@5.9.3))(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.7.0)
|
||||
ws: 8.18.1
|
||||
optionalDependencies:
|
||||
playwright: 1.52.0
|
||||
|
|
@ -17022,6 +17043,17 @@ snapshots:
|
|||
dependencies:
|
||||
tinyspy: 3.0.2
|
||||
|
||||
'@vitest/ui@3.0.8(vitest@3.0.8)':
|
||||
dependencies:
|
||||
'@vitest/utils': 3.0.8
|
||||
fflate: 0.8.2
|
||||
flatted: 3.3.3
|
||||
pathe: 2.0.3
|
||||
sirv: 3.0.1
|
||||
tinyglobby: 0.2.15
|
||||
tinyrainbow: 2.0.0
|
||||
vitest: 3.0.8(@types/debug@4.1.12)(@types/node@22.13.10)(@vitest/browser@3.0.8)(@vitest/ui@3.0.8)(jiti@2.6.1)(jsdom@20.0.3)(lightningcss@1.30.2)(msw@2.7.3(@types/node@22.13.10)(typescript@5.9.3))(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.7.0)
|
||||
|
||||
'@vitest/utils@3.0.8':
|
||||
dependencies:
|
||||
'@vitest/pretty-format': 3.0.8
|
||||
|
|
@ -19816,6 +19848,8 @@ snapshots:
|
|||
|
||||
diff@4.0.2: {}
|
||||
|
||||
diff@8.0.2: {}
|
||||
|
||||
dir-glob@3.0.1:
|
||||
dependencies:
|
||||
path-type: 4.0.0
|
||||
|
|
@ -20707,6 +20741,8 @@ snapshots:
|
|||
|
||||
fflate@0.4.8: {}
|
||||
|
||||
fflate@0.8.2: {}
|
||||
|
||||
file-entry-cache@10.0.7:
|
||||
dependencies:
|
||||
flat-cache: 6.1.7
|
||||
|
|
@ -22306,11 +22342,6 @@ snapshots:
|
|||
|
||||
js-tokens@4.0.0: {}
|
||||
|
||||
js-yaml@3.13.1:
|
||||
dependencies:
|
||||
argparse: 1.0.10
|
||||
esprima: 4.0.1
|
||||
|
||||
js-yaml@3.14.1:
|
||||
dependencies:
|
||||
argparse: 1.0.10
|
||||
|
|
@ -25765,7 +25796,7 @@ snapshots:
|
|||
|
||||
third-party-web@0.26.5: {}
|
||||
|
||||
third-party-web@0.28.0: {}
|
||||
third-party-web@0.29.0: {}
|
||||
|
||||
through@2.3.8: {}
|
||||
|
||||
|
|
@ -25777,11 +25808,6 @@ snapshots:
|
|||
|
||||
tinyexec@0.3.2: {}
|
||||
|
||||
tinyglobby@0.2.12:
|
||||
dependencies:
|
||||
fdir: 6.4.3(picomatch@4.0.2)
|
||||
picomatch: 4.0.2
|
||||
|
||||
tinyglobby@0.2.13:
|
||||
dependencies:
|
||||
fdir: 6.4.4(picomatch@4.0.2)
|
||||
|
|
@ -26293,7 +26319,7 @@ snapshots:
|
|||
|
||||
vite-plugin-dts@4.5.3(@types/node@22.13.10)(rollup@4.53.3)(typescript@5.9.3)(vite@6.3.5(@types/node@22.13.10)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.7.0)):
|
||||
dependencies:
|
||||
'@microsoft/api-extractor': 7.52.1(@types/node@22.13.10)
|
||||
'@microsoft/api-extractor': 7.55.1(@types/node@22.13.10)
|
||||
'@rollup/pluginutils': 5.1.4(rollup@4.53.3)
|
||||
'@volar/typescript': 2.4.12
|
||||
'@vue/language-core': 2.2.0(typescript@5.9.3)
|
||||
|
|
@ -26415,7 +26441,7 @@ snapshots:
|
|||
optionalDependencies:
|
||||
vite: 7.2.2(@types/node@22.13.10)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.7.0)
|
||||
|
||||
vitest@3.0.8(@types/debug@4.1.12)(@types/node@22.13.10)(@vitest/browser@3.0.8)(jiti@2.6.1)(jsdom@20.0.3)(lightningcss@1.30.2)(msw@2.7.3(@types/node@22.13.10)(typescript@5.9.3))(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.7.0):
|
||||
vitest@3.0.8(@types/debug@4.1.12)(@types/node@22.13.10)(@vitest/browser@3.0.8)(@vitest/ui@3.0.8)(jiti@2.6.1)(jsdom@20.0.3)(lightningcss@1.30.2)(msw@2.7.3(@types/node@22.13.10)(typescript@5.9.3))(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.7.0):
|
||||
dependencies:
|
||||
'@vitest/expect': 3.0.8
|
||||
'@vitest/mocker': 3.0.8(msw@2.7.3(@types/node@22.13.10)(typescript@5.9.3))(vite@6.3.5(@types/node@22.13.10)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.7.0))
|
||||
|
|
@ -26441,6 +26467,7 @@ snapshots:
|
|||
'@types/debug': 4.1.12
|
||||
'@types/node': 22.13.10
|
||||
'@vitest/browser': 3.0.8(@testing-library/dom@10.4.0)(@types/node@22.13.10)(playwright@1.52.0)(typescript@5.9.3)(vite@6.3.5(@types/node@22.13.10)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.85.1)(terser@5.39.0)(tsx@4.20.6)(yaml@2.7.0))(vitest@3.0.8)
|
||||
'@vitest/ui': 3.0.8(vitest@3.0.8)
|
||||
jsdom: 20.0.3
|
||||
transitivePeerDependencies:
|
||||
- jiti
|
||||
|
|
|
|||
|
|
@ -3,19 +3,19 @@ packages:
|
|||
- harper-wasm/pkg
|
||||
- packages/harper.js/examples/*
|
||||
catalog:
|
||||
typescript: ^5.8.2
|
||||
typescript: ^5.9.3
|
||||
tslib: ^2.8.1
|
||||
'@types/node': ^22.13.10
|
||||
'@babel/runtime': ^7.26.10
|
||||
"@types/node": ^22.13.10
|
||||
"@babel/runtime": ^7.26.10
|
||||
onlyBuiltDependencies:
|
||||
- '@biomejs/biome'
|
||||
- '@parcel/watcher'
|
||||
- '@swc/core'
|
||||
- '@vscode/vsce-sign'
|
||||
- "@biomejs/biome"
|
||||
- "@parcel/watcher"
|
||||
- "@swc/core"
|
||||
- "@vscode/vsce-sign"
|
||||
- core-js
|
||||
- core-js-pure
|
||||
- esbuild
|
||||
- keytar
|
||||
- msw
|
||||
- svelte-preprocess
|
||||
- '@tailwindcss/oxide'
|
||||
- "@tailwindcss/oxide"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue