@kubohiroya/turbowarp-structured-data 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +38 -0
- package/README.md +61 -7
- package/dist/structured-data.js +43 -22
- package/docs/.nojekyll +0 -0
- package/docs/assets/github-mark.svg +1 -0
- package/docs/assets/site.css +847 -0
- package/docs/index.html +577 -21
- package/docs/ja/index.html +549 -0
- package/lib-editor/src/config.d.ts +6 -0
- package/lib-module/src/bundle-module.d.ts +7 -0
- package/lib-module/src/bundle-module.js +1384 -0
- package/lib-module/src/codecs.d.ts +10 -0
- package/lib-module/src/config.d.ts +25 -0
- package/lib-module/src/core.d.ts +34 -0
- package/lib-module/src/editor-schema.d.ts +2 -0
- package/lib-module/src/extension.d.ts +74 -0
- package/lib-module/src/fixed-input-editors.d.ts +9 -0
- package/lib-module/src/fixed-input-schema.d.ts +3 -0
- package/lib-module/src/runtime-api.d.ts +41 -0
- package/lib-module/src/source-editor.d.ts +8 -0
- package/lib-module/src/structured-provider.d.ts +33 -0
- package/package.json +19 -11
- package/src/bundle-module.ts +23 -0
- package/src/config.ts +11 -0
- package/src/extension.ts +17 -15
- package/src/globals.d.ts +7 -36
- package/src/index.ts +2 -2
- package/src/runtime-api.ts +43 -0
- package/src/structured-provider.ts +38 -7
- package/templates/README.ja.md +36 -0
- package/templates/README.md +48 -6
package/README.ja.md
CHANGED
|
@@ -23,6 +23,8 @@ namespaceとloop contextがTurboWarp BlockUtilityのtarget/thread identityを使
|
|
|
23
23
|
|
|
24
24
|
JSON/YAML入力は256 KiB、深さ64、50,000 valueまでです。YAML alias、warning、unknown tag、duplicate key、string以外のmap key、未対応scalarは拒否します。
|
|
25
25
|
|
|
26
|
+
structured-data providerはnamed-data 0.4.0を介してbindingの任意の`schemaRef`を伝播できます。IDは`^[a-z][a-z0-9.-]{0,127}$`に一致し、versionは完全なSemVerである必要があります。Schema identityの解決は起動時固定で、明示的に有効化するまで既定OFFです。provider読み込み前に`globalThis.__TW_NAMED_DATA_FEATURE_FLAGS__ = {NAMED_DATA_SCHEMA_REF: true}`を設定します。参照はbindingの安定IDと完全なSemVer versionに一致する必要があります。providerはSchema本体を保持せず、別versionへのfallbackもしません。consumerは自身のSchema catalogでidentityを解決し、既存のJSON Schema実装で値を検証します。合意するsubsetは`type`、`properties`、`required`、Boolean形式の`additionalProperties`、`items`、`enum`、`const`、数値範囲、文字列/配列の長さ制約です。未対応keywordは検証動作を追加しません。flagをOFFにすればschema identityなしのmetadataへ即時に戻せます。
|
|
27
|
+
|
|
26
28
|
## クイックスタート
|
|
27
29
|
|
|
28
30
|
```text
|
|
@@ -63,6 +65,42 @@ arrayはindex昇順、objectはUnicodeコードポイント順で反復します
|
|
|
63
65
|
|
|
64
66
|
`dist/extension-manifest.json` format version 3はtarget-local named reference、型付きpath、argument/result型、effect、error、IR v2 operationを宣言します。[architecture](docs/architecture.ja.md)、[JSON Schema](schemas/extension-manifest.schema.json)、[semantic parity fixture](tests/fixtures/semantic-parity.json)を参照してください。
|
|
65
67
|
|
|
68
|
+
## 統合ビルド用module API
|
|
69
|
+
|
|
70
|
+
このソースのbuildは、単体JSとは別に、統合用のESM入口`./bundle-module`と
|
|
71
|
+
型宣言を`lib-module/`へ生成します。
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import {bundleModuleMetadata, createExtension, type ScratchApi}
|
|
75
|
+
from '@kubohiroya/turbowarp-structured-data/bundle-module';
|
|
76
|
+
|
|
77
|
+
export function createMember(memberScratch: ScratchApi) {
|
|
78
|
+
return createExtension(memberScratch);
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
import時はglobal Scratch / window / documentを参照せず、拡張の生成・登録を行いません。
|
|
83
|
+
明示的なcreateExtension(memberScratch)ごとに新しいinstanceを返し、後から実行する
|
|
84
|
+
ブロック・編集用補助処理・lifecycle callbackも同じhostを使います。factoryは
|
|
85
|
+
Scratch.extensions.registerを呼びません。単体entryも同じfactoryを使い、登録は1回です。
|
|
86
|
+
|
|
87
|
+
凍結されたbundleModuleMetadataはformatVersion: 1、元のid、unsandboxed条件を
|
|
88
|
+
宣言します。統合hostが生成前に検査し、登録とdisposeを管理します。ID・opcode・
|
|
89
|
+
保存データ形式を変更しません。
|
|
90
|
+
|
|
91
|
+
既存のSTRUCTURED_DATA_MVP・NAMED_DATA_REGISTRY_MVP・Schema参照の起動フラグと既定値を維持します。生成時の任意の編集登録・named-data初期化には注入hostを使います。dispose()をawaitして、このinstanceの登録とlistenerを解除します。StructuredDataExtensionを直接newする内部コードでは、hostを先頭に渡し、その後に従来の任意の機能フラグ引数を渡します。
|
|
92
|
+
|
|
93
|
+
yaml等のruntime依存とそのsubpathは外部importのまま保持します。既存の小さな編集用
|
|
94
|
+
純粋ヘルパーだけを含め、production consumerには編集packageやGUIエンジンを要求しません。
|
|
95
|
+
公開型は既存tsconfigと同じES2022の型ライブラリを使い、生成JSはES2020を対象とします。
|
|
96
|
+
既存exportsを維持して./bundle-moduleを追加し、templateへのruntime依存は追加しません。
|
|
97
|
+
|
|
98
|
+
pnpm run build:moduleで生成し、pnpm run check:moduleは実tarballをproduction依存だけの
|
|
99
|
+
consumerへinstallしてhost分離・単体版との動作一致・公開型・編集エンジンの非混入を検査します。
|
|
100
|
+
sb3-toolchain側の統合buildは[sb3-toolchain #65](https://github.com/kubohiroya/sb3-toolchain/issues/65)の後続です。
|
|
101
|
+
切戻しはこのmodule入口を選択せず従来のclassic distを読み込みます。新しいruntimeフラグや
|
|
102
|
+
保存データの移行は導入しません。
|
|
103
|
+
|
|
66
104
|
## 開発
|
|
67
105
|
|
|
68
106
|
```bash
|
package/README.md
CHANGED
|
@@ -22,10 +22,22 @@ The `STRUCTURED_DATA_MVP` feature flag is fixed at extension startup and default
|
|
|
22
22
|
|
|
23
23
|
JSON and YAML input is limited to 256 KiB, nesting depth 64, and 50,000 values. YAML aliases, warnings, unknown tags, duplicate keys, non-string map keys, and unsupported scalar types are rejected.
|
|
24
24
|
|
|
25
|
+
The structured-data provider can carry a binding's optional `schemaRef` through named-data 0.4.0.
|
|
26
|
+
The ID must match `^[a-z][a-z0-9.-]{0,127}$` and the version must be a complete SemVer version.
|
|
27
|
+
Schema identity resolution is a startup-fixed opt-in and defaults to `false`; configure
|
|
28
|
+
`globalThis.__TW_NAMED_DATA_FEATURE_FLAGS__ = {NAMED_DATA_SCHEMA_REF: true}` before loading the
|
|
29
|
+
provider. A request must match the binding's stable ID and full SemVer version exactly. The
|
|
30
|
+
provider does not store schema documents or choose a fallback version. Consumers resolve the
|
|
31
|
+
identity in their own schema catalog and validate the returned value with their existing JSON
|
|
32
|
+
Schema implementation. The agreed subset is `type`, `properties`, `required`,
|
|
33
|
+
`additionalProperties` (boolean), `items`, `enum`, `const`, numeric bounds, and string/array
|
|
34
|
+
length bounds; unsupported keywords do not add validation behavior. Turn the flag off to
|
|
35
|
+
immediately return to metadata without schema identities.
|
|
36
|
+
|
|
25
37
|
## Installation
|
|
26
38
|
|
|
27
39
|
```bash
|
|
28
|
-
pnpm add --save-exact @kubohiroya/turbowarp-structured-data@0.
|
|
40
|
+
pnpm add --save-exact @kubohiroya/turbowarp-structured-data@0.7.0
|
|
29
41
|
```
|
|
30
42
|
|
|
31
43
|
## Quick start
|
|
@@ -232,6 +244,48 @@ Return the current iteration value as JSON.
|
|
|
232
244
|
|
|
233
245
|
`dist/extension-manifest.json` format version 3 declares the target-local named reference model, typed path segments, block argument/result types, effects, stable errors, and IR v2 operations. See [architecture](docs/architecture.md), the [JSON Schema](schemas/extension-manifest.schema.json), and [semantic parity fixtures](tests/fixtures/semantic-parity.json).
|
|
234
246
|
|
|
247
|
+
## Integrated-build module API
|
|
248
|
+
|
|
249
|
+
Building this source also produces a `./bundle-module` ESM entry and declarations
|
|
250
|
+
in `lib-module/`. This entry is separate from the standalone JavaScript file.
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
import {bundleModuleMetadata, createExtension, type ScratchApi}
|
|
254
|
+
from '@kubohiroya/turbowarp-structured-data/bundle-module';
|
|
255
|
+
|
|
256
|
+
export function createMember(memberScratch: ScratchApi) {
|
|
257
|
+
return createExtension(memberScratch);
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Importing the entry does not access global Scratch / window / document or create
|
|
262
|
+
and register an extension. Each explicit createExtension(memberScratch) call
|
|
263
|
+
returns a fresh instance bound to that host, including deferred block execution,
|
|
264
|
+
editor helpers and lifecycle callbacks. The factory does not call
|
|
265
|
+
Scratch.extensions.register; the standalone entry uses the same factory and
|
|
266
|
+
registers exactly once.
|
|
267
|
+
|
|
268
|
+
The frozen bundleModuleMetadata declares formatVersion: 1, the original id and
|
|
269
|
+
unsandboxed requirement. An integrated host validates these before creation and
|
|
270
|
+
owns registration and disposal. Existing IDs, opcodes and saved data stay unchanged.
|
|
271
|
+
|
|
272
|
+
The existing STRUCTURED_DATA_MVP, NAMED_DATA_REGISTRY_MVP and Schema reference startup flags retain their defaults. Creation performs the existing optional editor and named-data initialization against the injected host. Call and await dispose() to release the instance registrations and listeners. Internal callers constructing StructuredDataExtension directly now pass the host first, followed by the existing optional feature arguments.
|
|
273
|
+
|
|
274
|
+
Runtime dependencies (including yaml and their subpaths) remain external imports.
|
|
275
|
+
Only the existing small, pure development-time editor helpers are included, so
|
|
276
|
+
production consumers need no editor package or GUI engine. Public types use the
|
|
277
|
+
same ES2022 libraries as the project tsconfig; generated JavaScript targets ES2020.
|
|
278
|
+
The package retains its existing exports and adds ./bundle-module; no template
|
|
279
|
+
runtime dependency is required.
|
|
280
|
+
|
|
281
|
+
pnpm run build:module builds this entry; pnpm run check:module packs and installs
|
|
282
|
+
the actual package with production dependencies only, checks host isolation,
|
|
283
|
+
standalone parity and public types, and rejects editor-engine dependency leaks.
|
|
284
|
+
The integrated sb3-toolchain build remains a later step in
|
|
285
|
+
[sb3-toolchain #65](https://github.com/kubohiroya/sb3-toolchain/issues/65).
|
|
286
|
+
To roll back, continue loading the existing classic dist artifact without selecting
|
|
287
|
+
this module entry. No runtime flag or saved-data migration is introduced.
|
|
288
|
+
|
|
235
289
|
## Development
|
|
236
290
|
|
|
237
291
|
```bash
|
|
@@ -246,15 +300,15 @@ SPDX-License-Identifier: MPL-2.0
|
|
|
246
300
|
|
|
247
301
|
Bundled third-party license terms are listed in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
|
|
248
302
|
|
|
249
|
-
##
|
|
303
|
+
## Fixed-input editor form (S3-4)
|
|
250
304
|
|
|
251
|
-
|
|
305
|
+
When the shared editor's startup flag `blockEditorFixedInputs` and Dialogs are both on in the GUI, the extension registers a fixed form for `forEachAtPath`'s `MAX` input only. Older GUIs, or a GUI with the flag off, get no extra registration. The canonical Schema is `schemas/block-editor-fixed-inputs.schema.json#/$defs/forEachAtPath/properties/MAX`; the codec and registration live in `src/fixed-input-editors.ts`. Saving without changes never rewrites existing raw values, unchanged aliases, or unknown enum values, and connected reporters are never evaluated. Only explicit changes are validated; other arguments, block declarations, and the saved format are unchanged.
|
|
252
306
|
|
|
253
|
-
MAX
|
|
307
|
+
`MAX` is an integer from 1 to 1000. New input also follows the shared finite-number token rule, and partial input is not saved. When the MVP flag is off nothing is registered, and whether `NAME`/`PATH` accept connected reporters (derived from `staticLiteral`) does not change.
|
|
254
308
|
|
|
255
|
-
|
|
309
|
+
Registration is limited to the optional API (`apiVersion: 1`) and is released on `RUNTIME_DISPOSED` or an explicit dispose. Turning the startup flag off and reloading restores the previous behavior. When rolling back the dependency, restore the manifest, lockfile, and actual resolution together. This stage does not include an npm release or dynamic candidates from later stages.
|
|
256
310
|
|
|
257
|
-
Schema
|
|
258
|
-
|
|
311
|
+
The contract the Schema describes is grounded in the actual `getInfo` declarations and the existing pure runtime conversions. The SchemaBundle `retrievalUri` identifies this local document; it does not mean the Schema is served from that URL or that `$ref` is resolved over HTTP. The Schema compiles from the bundled documents only.
|
|
312
|
+
Existing non-empty finite Number aliases for `MAX` (for example `001`, `+1`, or `0x10`) are only projected through `Number` for display; unchanged raw values are not saved again. Blank, non-finite, or unprojectable values are read-only, and no `0` or default is substituted. New input does not accept these aliases and follows NP-finite-new-input-v1.
|
|
259
313
|
|
|
260
314
|
Registration uses the optional editor API available when the extension instance is constructed. Adding or replacing that API later is not followed automatically; reload the GUI and reconstruct the extension instance after changing the startup configuration.
|
package/dist/structured-data.js
CHANGED
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
(function (Scratch) {
|
|
8
8
|
'use strict';
|
|
9
9
|
|
|
10
|
+
function isNamedDataSchemaRefEnabled(source = globalThis) {
|
|
11
|
+
const value = source.__TW_NAMED_DATA_FEATURE_FLAGS__?.NAMED_DATA_SCHEMA_REF;
|
|
12
|
+
return value === void 0 ? false : value === true || value === "true";
|
|
13
|
+
}
|
|
10
14
|
function isStructuredDataMvpEnabled(source = globalThis) {
|
|
11
15
|
const value = source.STRUCTURED_DATA_MVP;
|
|
12
16
|
return value === void 0 ? false : value === true || value === "true";
|
|
@@ -6799,6 +6803,7 @@
|
|
|
6799
6803
|
...opened.digest === void 0 ? {} : { digest: opened.digest },
|
|
6800
6804
|
revision: opened.revision,
|
|
6801
6805
|
replayable: opened.replayable,
|
|
6806
|
+
...opened.schemaRef === void 0 ? {} : { schemaRef: opened.schemaRef },
|
|
6802
6807
|
body: opened.body,
|
|
6803
6808
|
release: tracked.release
|
|
6804
6809
|
});
|
|
@@ -6964,9 +6969,10 @@
|
|
|
6964
6969
|
var STRUCTURED_DATA_NAMESPACE = "structured";
|
|
6965
6970
|
var STRUCTURED_BODY_MAX_BYTES = 262144;
|
|
6966
6971
|
var StructuredDataNamedDataProvider = class {
|
|
6967
|
-
constructor(store, maxBodyBytes = STRUCTURED_BODY_MAX_BYTES) {
|
|
6972
|
+
constructor(store, maxBodyBytes = STRUCTURED_BODY_MAX_BYTES, schemaRefEnabled = isNamedDataSchemaRefEnabled()) {
|
|
6968
6973
|
this.store = store;
|
|
6969
6974
|
this.maxBodyBytes = maxBodyBytes;
|
|
6975
|
+
this.schemaRefEnabled = schemaRefEnabled;
|
|
6970
6976
|
this.namespace = STRUCTURED_DATA_NAMESPACE;
|
|
6971
6977
|
this.kind = "structured";
|
|
6972
6978
|
this.openBodies = /* @__PURE__ */ new Set();
|
|
@@ -6977,7 +6983,7 @@
|
|
|
6977
6983
|
}
|
|
6978
6984
|
stat(reference, representation, context) {
|
|
6979
6985
|
const resolved = this.resolve(reference, representation, context);
|
|
6980
|
-
return this.metadata(reference, resolved.nativeRepresentation, representation, resolved.bytes.byteLength, resolved.revision);
|
|
6986
|
+
return this.metadata(reference, resolved.nativeRepresentation, representation, resolved.bytes.byteLength, resolved.revision, resolved.schemaRef);
|
|
6981
6987
|
}
|
|
6982
6988
|
openBody(reference, representation, context) {
|
|
6983
6989
|
const resolved = this.resolve(reference, representation, context);
|
|
@@ -6985,7 +6991,7 @@
|
|
|
6985
6991
|
this.openBodies.add(handle);
|
|
6986
6992
|
let released = false;
|
|
6987
6993
|
return {
|
|
6988
|
-
...this.metadata(reference, resolved.nativeRepresentation, representation, resolved.bytes.byteLength, resolved.revision),
|
|
6994
|
+
...this.metadata(reference, resolved.nativeRepresentation, representation, resolved.bytes.byteLength, resolved.revision, resolved.schemaRef),
|
|
6989
6995
|
body: resolved.bytes,
|
|
6990
6996
|
release: () => {
|
|
6991
6997
|
if (released) return;
|
|
@@ -7007,6 +7013,9 @@
|
|
|
7007
7013
|
this.throwIfAborted(context.signal);
|
|
7008
7014
|
const binding = this.store.get(context.target, reference.name);
|
|
7009
7015
|
if (!binding) throw new NamedDataError("NAMED_DATA_NOT_FOUND", `Structured data does not exist: ${reference.name}`);
|
|
7016
|
+
const requestedSchemaRef = reference.schemaRef;
|
|
7017
|
+
if (requestedSchemaRef !== void 0 && !this.schemaRefEnabled) throw new NamedDataError("NAMED_DATA_SCHEMA_UNRESOLVED", "Schema reference resolution is disabled.");
|
|
7018
|
+
if (requestedSchemaRef !== void 0 && (binding.schemaRef?.id !== requestedSchemaRef.id || binding.schemaRef?.version !== requestedSchemaRef.version)) throw new NamedDataError("NAMED_DATA_SCHEMA_VERSION_MISMATCH", "Binding schemaRef does not match the requested reference.");
|
|
7010
7019
|
const text = this.render(binding.value, representation);
|
|
7011
7020
|
const bytes = new TextEncoder().encode(text);
|
|
7012
7021
|
if (bytes.byteLength > this.maxBodyBytes) throw new NamedDataError("NAMED_DATA_BODY_TOO_LARGE", `Encoded body is ${bytes.byteLength} bytes; maximum is ${this.maxBodyBytes}.`);
|
|
@@ -7014,7 +7023,8 @@
|
|
|
7014
7023
|
return {
|
|
7015
7024
|
bytes,
|
|
7016
7025
|
revision: binding.revision,
|
|
7017
|
-
nativeRepresentation: binding.nativeRepresentation
|
|
7026
|
+
nativeRepresentation: binding.nativeRepresentation,
|
|
7027
|
+
...requestedSchemaRef === void 0 ? {} : { schemaRef: binding.schemaRef }
|
|
7018
7028
|
};
|
|
7019
7029
|
}
|
|
7020
7030
|
validateReference(reference, context) {
|
|
@@ -7027,7 +7037,7 @@
|
|
|
7027
7037
|
if (representation === "yaml") return renderYamlDocument(value);
|
|
7028
7038
|
throw new NamedDataError("NAMED_DATA_REPRESENTATION_UNSUPPORTED", `Structured data cannot be rendered as ${representation}.`);
|
|
7029
7039
|
}
|
|
7030
|
-
metadata(reference, nativeRepresentation, representation, byteLength, revision) {
|
|
7040
|
+
metadata(reference, nativeRepresentation, representation, byteLength, revision, schemaRef) {
|
|
7031
7041
|
return {
|
|
7032
7042
|
reference: { ...reference },
|
|
7033
7043
|
nativeRepresentation,
|
|
@@ -7035,7 +7045,8 @@
|
|
|
7035
7045
|
mediaType: representation === "json" ? "application/json; charset=utf-8" : "application/yaml; charset=utf-8",
|
|
7036
7046
|
byteLength,
|
|
7037
7047
|
revision: String(revision),
|
|
7038
|
-
replayable: true
|
|
7048
|
+
replayable: true,
|
|
7049
|
+
...schemaRef === void 0 ? {} : { schemaRef }
|
|
7039
7050
|
};
|
|
7040
7051
|
}
|
|
7041
7052
|
throwIfAborted(signal) {
|
|
@@ -7045,14 +7056,15 @@
|
|
|
7045
7056
|
var LOOP_STATE = "structuredDataLoopState";
|
|
7046
7057
|
var blockDefinitions = block_definitions_default.blocks;
|
|
7047
7058
|
var StructuredDataExtension = class {
|
|
7048
|
-
constructor(enabled = isStructuredDataMvpEnabled(), namedDataEnabled = isNamedDataRegistryMvpEnabled()) {
|
|
7059
|
+
constructor(scratch, enabled = isStructuredDataMvpEnabled(), namedDataEnabled = isNamedDataRegistryMvpEnabled()) {
|
|
7060
|
+
this.scratch = scratch;
|
|
7049
7061
|
this.disposed = false;
|
|
7050
7062
|
this.registries = /* @__PURE__ */ new WeakMap();
|
|
7051
7063
|
this.iterationStacks = /* @__PURE__ */ new WeakMap();
|
|
7052
7064
|
this.nextRevision = 1;
|
|
7053
7065
|
this.enabled = enabled;
|
|
7054
|
-
this.unregisterSourceEditors = registerSourceEditors(
|
|
7055
|
-
const runtime =
|
|
7066
|
+
this.unregisterSourceEditors = registerSourceEditors(this.scratch, enabled ? sourceEditorDefinitions : []);
|
|
7067
|
+
const runtime = this.scratch.vm?.runtime;
|
|
7056
7068
|
const onDispose = () => {
|
|
7057
7069
|
this.dispose();
|
|
7058
7070
|
};
|
|
@@ -7063,11 +7075,11 @@
|
|
|
7063
7075
|
};
|
|
7064
7076
|
let unregisterFixed = () => {};
|
|
7065
7077
|
try {
|
|
7066
|
-
unregisterFixed = registerFixedInputEditors(
|
|
7078
|
+
unregisterFixed = registerFixedInputEditors(this.scratch, enabled ? fixedInputEditorDefinitions : []);
|
|
7067
7079
|
this.unregisterFixedInputEditors = unregisterFixed;
|
|
7068
7080
|
if (namedDataEnabled) {
|
|
7069
7081
|
this.namedDataProvider = new StructuredDataNamedDataProvider({ get: (target, name) => this.registries.get(target)?.get(name) });
|
|
7070
|
-
const runtime =
|
|
7082
|
+
const runtime = this.scratch.vm?.runtime;
|
|
7071
7083
|
if (runtime) {
|
|
7072
7084
|
this.namedDataRegistry = installNamedDataRegistry(runtime);
|
|
7073
7085
|
this.namedDataRegistration = this.namedDataRegistry.registerProvider(this.namedDataProvider, { lifetime: "persistent" });
|
|
@@ -7103,17 +7115,17 @@
|
|
|
7103
7115
|
getInfo() {
|
|
7104
7116
|
return {
|
|
7105
7117
|
id: extensionConfig.id,
|
|
7106
|
-
name:
|
|
7118
|
+
name: this.scratch.translate(block_definitions_default.extensionName),
|
|
7107
7119
|
docsURI: extensionConfig.docsURI,
|
|
7108
7120
|
blockIconURI: extensionConfig.blockIconURI,
|
|
7109
7121
|
blocks: this.enabled ? blockDefinitions.map((block) => this.toScratchBlock(block)) : []
|
|
7110
7122
|
};
|
|
7111
7123
|
}
|
|
7112
7124
|
parseJson(args, util) {
|
|
7113
|
-
this.store(util.target, args.NAME, parseJsonDocument(
|
|
7125
|
+
this.store(util.target, args.NAME, parseJsonDocument(this.scratch.Cast.toString(args.TEXT)), "json");
|
|
7114
7126
|
}
|
|
7115
7127
|
parseYaml(args, util) {
|
|
7116
|
-
this.store(util.target, args.NAME, parseYamlDocument(
|
|
7128
|
+
this.store(util.target, args.NAME, parseYamlDocument(this.scratch.Cast.toString(args.TEXT)), "yaml");
|
|
7117
7129
|
}
|
|
7118
7130
|
toJson(args, util) {
|
|
7119
7131
|
return renderJsonDocument(this.requireData(util.target, args.NAME));
|
|
@@ -7137,7 +7149,7 @@
|
|
|
7137
7149
|
}
|
|
7138
7150
|
setJsonAtPath(args, util) {
|
|
7139
7151
|
const name = this.name(args.NAME);
|
|
7140
|
-
const updated = setAtPath(this.requireDataByName(util.target, name), this.path(args.PATH), parseJson(
|
|
7152
|
+
const updated = setAtPath(this.requireDataByName(util.target, name), this.path(args.PATH), parseJson(this.scratch.Cast.toString(args.VALUE)));
|
|
7141
7153
|
this.setBinding(util.target, name, updated);
|
|
7142
7154
|
}
|
|
7143
7155
|
deleteAtPath(args, util) {
|
|
@@ -7156,7 +7168,7 @@
|
|
|
7156
7168
|
const stack = this.stackFor(util.thread);
|
|
7157
7169
|
if (!state) {
|
|
7158
7170
|
state = {
|
|
7159
|
-
entries: iterationEntries(this.requireData(util.target, args.NAME), this.path(args.PATH),
|
|
7171
|
+
entries: iterationEntries(this.requireData(util.target, args.NAME), this.path(args.PATH), this.scratch.Cast.toNumber(args.MAX)),
|
|
7160
7172
|
cursor: 0,
|
|
7161
7173
|
active: false
|
|
7162
7174
|
};
|
|
@@ -7218,7 +7230,7 @@
|
|
|
7218
7230
|
this.nextRevision += 1;
|
|
7219
7231
|
}
|
|
7220
7232
|
name(value) {
|
|
7221
|
-
const name =
|
|
7233
|
+
const name = this.scratch.Cast.toString(value).trim();
|
|
7222
7234
|
if (name.length === 0) throw new StructuredDataError("INVALID_NAME", "Structured data name cannot be empty.");
|
|
7223
7235
|
return name;
|
|
7224
7236
|
}
|
|
@@ -7239,7 +7251,7 @@
|
|
|
7239
7251
|
return stack;
|
|
7240
7252
|
}
|
|
7241
7253
|
path(value) {
|
|
7242
|
-
return parsePath(
|
|
7254
|
+
return parsePath(this.scratch.Cast.toString(value));
|
|
7243
7255
|
}
|
|
7244
7256
|
clearRuntimeState() {
|
|
7245
7257
|
this.namedDataProvider?.clearSession();
|
|
@@ -7250,16 +7262,25 @@
|
|
|
7250
7262
|
toScratchBlock(block) {
|
|
7251
7263
|
return {
|
|
7252
7264
|
opcode: block.opcode,
|
|
7253
|
-
blockType:
|
|
7254
|
-
text:
|
|
7265
|
+
blockType: this.scratch.BlockType[block.blockType],
|
|
7266
|
+
text: this.scratch.translate(block.text),
|
|
7255
7267
|
arguments: Object.fromEntries(Object.entries(block.arguments).map(([name, argument]) => [name, {
|
|
7256
|
-
type:
|
|
7268
|
+
type: this.scratch.ArgumentType[argument.type],
|
|
7257
7269
|
defaultValue: argument.defaultValue
|
|
7258
7270
|
}]))
|
|
7259
7271
|
};
|
|
7260
7272
|
}
|
|
7261
7273
|
};
|
|
7274
|
+
Object.freeze({
|
|
7275
|
+
formatVersion: 1,
|
|
7276
|
+
id: extensionConfig.id,
|
|
7277
|
+
unsandboxed: extensionConfig.unsandboxed ? "required" : "not-needed"
|
|
7278
|
+
});
|
|
7279
|
+
/** The caller supplies the member host and owns registration and lifetime. */
|
|
7280
|
+
function createExtension(scratch) {
|
|
7281
|
+
return new StructuredDataExtension(scratch);
|
|
7282
|
+
}
|
|
7262
7283
|
if (extensionConfig.unsandboxed && !Scratch.extensions.unsandboxed) throw new Error(`${extensionConfig.name} must run unsandboxed.`);
|
|
7263
|
-
Scratch.extensions.register(
|
|
7284
|
+
Scratch.extensions.register(createExtension(Scratch));
|
|
7264
7285
|
|
|
7265
7286
|
})(Scratch);
|
package/docs/.nojekyll
ADDED
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10.226 17.284c-2.965-.36-5.054-2.493-5.054-5.256 0-1.123.404-2.336 1.078-3.144-.292-.741-.247-2.314.09-2.965.898-.112 2.111.36 2.83 1.01.853-.269 1.752-.404 2.853-.404 1.1 0 1.999.135 2.807.382.696-.629 1.932-1.1 2.83-.988.315.606.36 2.179.067 2.942.72.854 1.101 2 1.101 3.167 0 2.763-2.089 4.852-5.098 5.234.763.494 1.28 1.572 1.28 2.807v2.336c0 .674.561 1.056 1.235.786 4.066-1.55 7.255-5.615 7.255-10.646C23.5 6.188 18.334 1 11.978 1 5.62 1 .5 6.188.5 12.545c0 4.986 3.167 9.12 7.435 10.669.606.225 1.19-.18 1.19-.786V20.63a2.9 2.9 0 0 1-1.078.224c-1.483 0-2.359-.808-2.987-2.313-.247-.607-.517-.966-1.034-1.033-.27-.023-.359-.135-.359-.27 0-.27.45-.471.898-.471.652 0 1.213.404 1.797 1.235.45.651.921.943 1.483.943.561 0 .92-.202 1.437-.719.382-.381.674-.718.944-.943"/></svg>
|