@wcstack/state 1.26.0 → 1.28.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 +100 -8
- package/README.md +103 -7
- package/dist/auto.min.js +1 -1
- package/dist/auto.min.js.map +1 -1
- package/dist/index.d.ts +70 -3
- package/dist/index.esm.js +1407 -174
- package/dist/index.esm.js.map +1 -1
- package/dist/manifest.d.ts +35 -0
- package/dist/manifest.esm.js +213 -2
- package/dist/parser.d.ts +74 -0
- package/dist/parser.esm.js +1452 -0
- package/dist/wcs-manifest.json +112 -1
- package/package.json +5 -1
package/dist/manifest.d.ts
CHANGED
|
@@ -57,6 +57,41 @@ interface IWcsManifest {
|
|
|
57
57
|
};
|
|
58
58
|
/** 構造ディレクティブ(`<template data-wcs="for: ...">` 等) */
|
|
59
59
|
structuralDirectives: readonly string[];
|
|
60
|
+
/**
|
|
61
|
+
* 修飾子(`#` 後)の語彙。flags は値を取らない形(`#prevent`)、keyValue は
|
|
62
|
+
* `=` で値を取る形(`#init=element`)、eventNamePrefix は `on` + イベント名の形
|
|
63
|
+
* (`#onchange` — two-way / radio / checkbox のイベント名上書き。README「Modifiers」)。
|
|
64
|
+
* define.ts の定数が単一正本で、ランタイムの消費箇所も同じ定数に分岐する。
|
|
65
|
+
*/
|
|
66
|
+
modifiers: {
|
|
67
|
+
flags: readonly string[];
|
|
68
|
+
keyValue: readonly string[];
|
|
69
|
+
eventNamePrefix: string;
|
|
70
|
+
};
|
|
71
|
+
/** リストインデックス参照名(`$1`..`$N`)。prefix + 1 始まり連番、maxDepth まで。 */
|
|
72
|
+
indexParam: {
|
|
73
|
+
prefix: string;
|
|
74
|
+
maxDepth: number;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* bindingType 判別の語彙(parseBindTextsForElement の分岐と同一の定数から導出)。
|
|
78
|
+
* 判別順: else → spread → 構造ディレクティブ/radio/checkbox → eventToken・`on*`
|
|
79
|
+
* (event)→ prop。propNamespaces は左辺先頭セグメントの特殊 namespace で、
|
|
80
|
+
* apply 層のディスパッチキー集合との一致はテストが強制する。
|
|
81
|
+
* 既知の未収載: `radio` / `checkbox`(BindingType union のみが正本)。
|
|
82
|
+
*/
|
|
83
|
+
bindingTypes: {
|
|
84
|
+
elseKeyword: string;
|
|
85
|
+
spread: string;
|
|
86
|
+
eventPropertyPrefix: string;
|
|
87
|
+
propNamespaces: {
|
|
88
|
+
eventToken: string;
|
|
89
|
+
command: string;
|
|
90
|
+
class: string;
|
|
91
|
+
attr: string;
|
|
92
|
+
style: string;
|
|
93
|
+
};
|
|
94
|
+
};
|
|
60
95
|
};
|
|
61
96
|
/** 組み込みフィルタ名(builtinFilters から自動導出=実装が正本) */
|
|
62
97
|
filters: string[];
|
package/dist/manifest.esm.js
CHANGED
|
@@ -71,6 +71,15 @@ function valueMustBeBoolean(fnName) {
|
|
|
71
71
|
function valueMustBeDate(fnName) {
|
|
72
72
|
raiseError(`filter ${fnName} requires a date value`);
|
|
73
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Throws error when filter requires array value but non-array provided.
|
|
76
|
+
*
|
|
77
|
+
* @param fnName - Name of the filter function
|
|
78
|
+
* @returns Never returns (always throws)
|
|
79
|
+
*/
|
|
80
|
+
function valueMustBeArray(fnName) {
|
|
81
|
+
raiseError(`filter ${fnName} requires an array value`);
|
|
82
|
+
}
|
|
74
83
|
|
|
75
84
|
/**
|
|
76
85
|
* builtinFilters.ts
|
|
@@ -83,7 +92,7 @@ function valueMustBeDate(fnName) {
|
|
|
83
92
|
* - Designed for common use as both input and output filters
|
|
84
93
|
*
|
|
85
94
|
* Design points:
|
|
86
|
-
* - Comprehensive coverage of diverse filters: eq, ne, lt, gt, inc, fix, locale, uc, lc, cap, trim, slice, pad, int, float, round, date, time, ymd, falsy, truthy, defaults, boolean, number, string, null, etc.
|
|
95
|
+
* - Comprehensive coverage of diverse filters: eq, ne, lt, gt, inc, abs, clamp, fix, locale, uc, lc, cap, trim, slice, pad, truncate, join, int, float, round, percent, unit, date, time, ymd, hms, falsy, truthy, defaults, boolean, number, string, null, etc.
|
|
87
96
|
* - Rich type checking and error handling for option values
|
|
88
97
|
* - Centralized management of filter functions with FilterWithOptions type, easy to extend
|
|
89
98
|
* - Dynamic retrieval of filter functions from filter names and options via builtinFilterFn
|
|
@@ -316,6 +325,48 @@ const mod = (options) => {
|
|
|
316
325
|
return value % Number(opt);
|
|
317
326
|
};
|
|
318
327
|
};
|
|
328
|
+
/**
|
|
329
|
+
* Absolute value filter - returns the magnitude of a number.
|
|
330
|
+
*
|
|
331
|
+
* @param options - Unused
|
|
332
|
+
* @returns Filter function that returns the absolute value
|
|
333
|
+
*/
|
|
334
|
+
const abs = (_options) => {
|
|
335
|
+
return (value) => {
|
|
336
|
+
if (typeof value !== 'number') {
|
|
337
|
+
valueMustBeNumber('abs');
|
|
338
|
+
}
|
|
339
|
+
return Math.abs(value);
|
|
340
|
+
};
|
|
341
|
+
};
|
|
342
|
+
/**
|
|
343
|
+
* Clamp filter - constrains a number to the inclusive range [min, max].
|
|
344
|
+
*
|
|
345
|
+
* Saturating conversion in the same family as round/floor/ceil, so it stays on
|
|
346
|
+
* the wire rather than in state. Pairs with `unit` for style bindings:
|
|
347
|
+
* `style.width: ratio|clamp(0,1)|percent(0)`.
|
|
348
|
+
*
|
|
349
|
+
* @param options - Array with minimum as first element and maximum as second (both required)
|
|
350
|
+
* @returns Filter function that returns the clamped number
|
|
351
|
+
*/
|
|
352
|
+
const clamp = (options) => {
|
|
353
|
+
const opt1 = options?.[0] ?? optionsRequired('clamp');
|
|
354
|
+
if (!validateNumberString(opt1)) {
|
|
355
|
+
optionMustBeNumber('clamp');
|
|
356
|
+
}
|
|
357
|
+
const opt2 = options?.[1] ?? optionsRequired('clamp');
|
|
358
|
+
if (!validateNumberString(opt2)) {
|
|
359
|
+
optionMustBeNumber('clamp');
|
|
360
|
+
}
|
|
361
|
+
const min = Number(opt1);
|
|
362
|
+
const max = Number(opt2);
|
|
363
|
+
return (value) => {
|
|
364
|
+
if (typeof value !== 'number') {
|
|
365
|
+
valueMustBeNumber('clamp');
|
|
366
|
+
}
|
|
367
|
+
return Math.min(Math.max(value, min), max);
|
|
368
|
+
};
|
|
369
|
+
};
|
|
319
370
|
/**
|
|
320
371
|
* Fixed decimal filter - formats number to fixed decimal places.
|
|
321
372
|
*
|
|
@@ -582,6 +633,76 @@ const percent = (options) => {
|
|
|
582
633
|
return `${(value * 100).toFixed(Number(opt))}%`;
|
|
583
634
|
};
|
|
584
635
|
};
|
|
636
|
+
/**
|
|
637
|
+
* Unit filter - appends a CSS unit (or any suffix) to the value.
|
|
638
|
+
*
|
|
639
|
+
* A number alone does nothing in CSS, so without this the unit has to be built in
|
|
640
|
+
* state — which drags presentation into the source of truth, and in the worst case
|
|
641
|
+
* forces a whole derived array just to carry `"42%"` strings.
|
|
642
|
+
* `style.height: samples.*.cpu|clamp(0,100)|fix(0)|unit(%)` keeps it on the wire.
|
|
643
|
+
*
|
|
644
|
+
* Accepts strings as well as numbers **on purpose**: the useful chains run through
|
|
645
|
+
* `fix` / `percent`, which already return strings. Rejecting non-numbers here would
|
|
646
|
+
* break exactly the combination this filter exists for.
|
|
647
|
+
*
|
|
648
|
+
* `null` / `undefined` pass through untouched rather than becoming `"undefinedpx"`,
|
|
649
|
+
* so the binding layer's "undefined skips the write, null clears" semantics survive.
|
|
650
|
+
*
|
|
651
|
+
* @param options - Array with the unit/suffix as first element (required)
|
|
652
|
+
* @returns Filter function that returns the value with the unit appended
|
|
653
|
+
*/
|
|
654
|
+
const unit = (options) => {
|
|
655
|
+
const opt = options?.[0] ?? optionsRequired('unit');
|
|
656
|
+
return (value) => {
|
|
657
|
+
if (value === null || typeof value === 'undefined') {
|
|
658
|
+
return value;
|
|
659
|
+
}
|
|
660
|
+
return String(value) + opt;
|
|
661
|
+
};
|
|
662
|
+
};
|
|
663
|
+
/**
|
|
664
|
+
* Join filter - joins array elements into a string.
|
|
665
|
+
*
|
|
666
|
+
* The default separator is `", "` rather than `","`: a bare comma is what `String()`
|
|
667
|
+
* already produces without any filter, so defaulting to it would make `|join` a no-op.
|
|
668
|
+
*
|
|
669
|
+
* @param options - Array with separator as first element (default: ', ')
|
|
670
|
+
* @returns Filter function that returns the joined string
|
|
671
|
+
*/
|
|
672
|
+
const join = (options) => {
|
|
673
|
+
const opt = options?.[0] ?? ', ';
|
|
674
|
+
return (value) => {
|
|
675
|
+
if (!Array.isArray(value)) {
|
|
676
|
+
valueMustBeArray('join');
|
|
677
|
+
}
|
|
678
|
+
return value.join(opt);
|
|
679
|
+
};
|
|
680
|
+
};
|
|
681
|
+
/**
|
|
682
|
+
* Truncate filter - shortens a string and appends an ellipsis.
|
|
683
|
+
*
|
|
684
|
+
* The length option counts **kept characters**, not the total including the suffix,
|
|
685
|
+
* matching the existing `slice(0, n)` reading. A string at or below the limit is
|
|
686
|
+
* returned untouched (no suffix).
|
|
687
|
+
*
|
|
688
|
+
* @param options - Array with max kept length as first element and suffix as second (default: '…')
|
|
689
|
+
* @returns Filter function that returns the truncated string
|
|
690
|
+
*/
|
|
691
|
+
const truncate = (options) => {
|
|
692
|
+
const opt1 = options?.[0] ?? optionsRequired('truncate');
|
|
693
|
+
if (!validateNumberString(opt1)) {
|
|
694
|
+
optionMustBeNumber('truncate');
|
|
695
|
+
}
|
|
696
|
+
const maxLength = Number(opt1);
|
|
697
|
+
const suffix = options?.[1] ?? '…';
|
|
698
|
+
return (value) => {
|
|
699
|
+
const v = String(value);
|
|
700
|
+
if (v.length <= maxLength) {
|
|
701
|
+
return v;
|
|
702
|
+
}
|
|
703
|
+
return v.slice(0, maxLength) + suffix;
|
|
704
|
+
};
|
|
705
|
+
};
|
|
585
706
|
/**
|
|
586
707
|
* Date filter - formats Date object as localized date string.
|
|
587
708
|
*
|
|
@@ -645,6 +766,27 @@ const ymd = (options) => {
|
|
|
645
766
|
return `${year}${opt}${month}${opt}${day}`;
|
|
646
767
|
};
|
|
647
768
|
};
|
|
769
|
+
/**
|
|
770
|
+
* Hour-Minute-Second filter - formats Date object as HH:MM:SS string.
|
|
771
|
+
*
|
|
772
|
+
* The counterpart of `ymd`: a fixed, zero-padded, locale-independent rendering with a
|
|
773
|
+
* configurable separator, for when `time` (locale-formatted) is not stable enough.
|
|
774
|
+
*
|
|
775
|
+
* @param options - Array with separator string as first element (default: ':')
|
|
776
|
+
* @returns Filter function that returns formatted time string
|
|
777
|
+
*/
|
|
778
|
+
const hms = (options) => {
|
|
779
|
+
const opt = options?.[0] ?? ':';
|
|
780
|
+
return (value) => {
|
|
781
|
+
if (!(value instanceof Date)) {
|
|
782
|
+
valueMustBeDate('hms');
|
|
783
|
+
}
|
|
784
|
+
const hours = value.getHours().toString().padStart(2, '0');
|
|
785
|
+
const minutes = value.getMinutes().toString().padStart(2, '0');
|
|
786
|
+
const seconds = value.getSeconds().toString().padStart(2, '0');
|
|
787
|
+
return `${hours}${opt}${minutes}${opt}${seconds}`;
|
|
788
|
+
};
|
|
789
|
+
};
|
|
648
790
|
/**
|
|
649
791
|
* Falsy filter - checks if value is falsy.
|
|
650
792
|
*
|
|
@@ -735,6 +877,8 @@ const builtinFilters = {
|
|
|
735
877
|
"mul": mul,
|
|
736
878
|
"div": div,
|
|
737
879
|
"mod": mod,
|
|
880
|
+
"abs": abs,
|
|
881
|
+
"clamp": clamp,
|
|
738
882
|
"fix": fix,
|
|
739
883
|
"locale": locale,
|
|
740
884
|
"uc": uc,
|
|
@@ -746,16 +890,20 @@ const builtinFilters = {
|
|
|
746
890
|
"pad": pad,
|
|
747
891
|
"rep": rep,
|
|
748
892
|
"rev": rev,
|
|
893
|
+
"truncate": truncate,
|
|
894
|
+
"join": join,
|
|
749
895
|
"int": int,
|
|
750
896
|
"float": float,
|
|
751
897
|
"round": round,
|
|
752
898
|
"floor": floor,
|
|
753
899
|
"ceil": ceil,
|
|
754
900
|
"percent": percent,
|
|
901
|
+
"unit": unit,
|
|
755
902
|
"date": date,
|
|
756
903
|
"time": time,
|
|
757
904
|
"datetime": datetime,
|
|
758
905
|
"ymd": ymd,
|
|
906
|
+
"hms": hms,
|
|
759
907
|
"falsy": falsy,
|
|
760
908
|
"truthy": truthy,
|
|
761
909
|
"defaults": defaults,
|
|
@@ -793,6 +941,8 @@ const builtinFilterMeta = {
|
|
|
793
941
|
mul: { description: "乗算", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
|
|
794
942
|
div: { description: "除算", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
|
|
795
943
|
mod: { description: "剰余", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
|
|
944
|
+
abs: { description: "絶対値", hasArgs: false, resultType: "number", acceptTypes: ["number"], minArgs: 0, maxArgs: 0 },
|
|
945
|
+
clamp: { description: "範囲内に丸める (min,max)", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 2, maxArgs: 2, argTypes: ["number", "number"] },
|
|
796
946
|
// 数値フォーマット
|
|
797
947
|
fix: { description: "固定小数点表記", hasArgs: true, resultType: "string", acceptTypes: ["number"], minArgs: 0, maxArgs: 1, argTypes: ["number"] },
|
|
798
948
|
locale: { description: "ロケール形式で数値フォーマット", hasArgs: true, resultType: "string", acceptTypes: ["number"], minArgs: 0, maxArgs: 1, argTypes: ["string"] },
|
|
@@ -806,6 +956,8 @@ const builtinFilterMeta = {
|
|
|
806
956
|
pad: { description: "パディング (length[,char])", hasArgs: true, resultType: "string", acceptTypes: ["string"], minArgs: 1, maxArgs: 2, argTypes: ["number", "string"] },
|
|
807
957
|
rep: { description: "繰り返し (count)", hasArgs: true, resultType: "string", acceptTypes: ["string"], minArgs: 1, maxArgs: 1, argTypes: ["number"] },
|
|
808
958
|
rev: { description: "文字順を反転", hasArgs: false, resultType: "string", acceptTypes: ["string"], minArgs: 0, maxArgs: 0 },
|
|
959
|
+
truncate: { description: "切り詰めて省略記号 (length[,suffix])", hasArgs: true, resultType: "string", acceptTypes: ["string"], minArgs: 1, maxArgs: 2, argTypes: ["number", "string"] },
|
|
960
|
+
join: { description: "配列を連結 ([separator])", hasArgs: true, resultType: "string", acceptTypes: ["array"], minArgs: 0, maxArgs: 1, argTypes: ["string"] },
|
|
809
961
|
// 数値パース・丸め
|
|
810
962
|
int: { description: "整数にパース", hasArgs: false, resultType: "number", acceptTypes: ["string", "number"], minArgs: 0, maxArgs: 0 },
|
|
811
963
|
float: { description: "浮動小数点数にパース", hasArgs: false, resultType: "number", acceptTypes: ["string", "number"], minArgs: 0, maxArgs: 0 },
|
|
@@ -813,11 +965,15 @@ const builtinFilterMeta = {
|
|
|
813
965
|
floor: { description: "切り下げ", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 0, maxArgs: 1, argTypes: ["number"] },
|
|
814
966
|
ceil: { description: "切り上げ", hasArgs: true, resultType: "number", acceptTypes: ["number"], minArgs: 0, maxArgs: 1, argTypes: ["number"] },
|
|
815
967
|
percent: { description: "パーセンテージ形式", hasArgs: true, resultType: "string", acceptTypes: ["number"], minArgs: 0, maxArgs: 1, argTypes: ["number"] },
|
|
968
|
+
// number だけでなく string も受ける。実用チェーンは fix / percent の後ろに繋がり、
|
|
969
|
+
// それらは既に string を返すため(builtinFilters.ts の unit を参照)
|
|
970
|
+
unit: { description: "単位(接尾辞)を付加", hasArgs: true, resultType: "string", acceptTypes: ["number", "string"], minArgs: 1, maxArgs: 1, argTypes: ["string"] },
|
|
816
971
|
// 日付・時刻
|
|
817
972
|
date: { description: "ロケール形式の日付", hasArgs: false, resultType: "string", acceptTypes: "any", minArgs: 0, maxArgs: 0 },
|
|
818
973
|
time: { description: "ロケール形式の時刻", hasArgs: false, resultType: "string", acceptTypes: "any", minArgs: 0, maxArgs: 0 },
|
|
819
974
|
datetime: { description: "ロケール形式の日時", hasArgs: false, resultType: "string", acceptTypes: "any", minArgs: 0, maxArgs: 0 },
|
|
820
975
|
ymd: { description: "YYYY-MM-DD 形式", hasArgs: true, resultType: "string", acceptTypes: "any", minArgs: 0, maxArgs: 1, argTypes: ["string"] },
|
|
976
|
+
hms: { description: "HH:MM:SS 形式", hasArgs: true, resultType: "string", acceptTypes: "any", minArgs: 0, maxArgs: 1, argTypes: ["string"] },
|
|
821
977
|
// 真偽値・変換
|
|
822
978
|
falsy: { description: "偽値か判定", hasArgs: false, resultType: "boolean", acceptTypes: "any", minArgs: 0, maxArgs: 0 },
|
|
823
979
|
truthy: { description: "真値か判定", hasArgs: false, resultType: "boolean", acceptTypes: "any", minArgs: 0, maxArgs: 0 },
|
|
@@ -845,6 +1001,38 @@ const PROP_VALUE_SEPARATOR = ':'; // 左辺(prop)と右辺(path)の区切り
|
|
|
845
1001
|
const MODIFIER_SEPARATOR = '#'; // prop と修飾子の区切り
|
|
846
1002
|
const STATE_NAME_SEPARATOR = '@'; // path と @stateName の区切り
|
|
847
1003
|
const FILTER_SEPARATOR = '|'; // フィルタパイプの区切り
|
|
1004
|
+
// 修飾子(`#` 後)の語彙(単一正本)。manifest.syntax.modifiers で公開される。
|
|
1005
|
+
// フラグ形(`#prevent` — 値を取らない)とキー値形(`#init=element` — `=` で値を取る)。
|
|
1006
|
+
// 消費箇所(event/handler・BindingSession・twowayHandler・bindings/initialSync)は
|
|
1007
|
+
// この定数を参照する — 文字列リテラルの散在は tooling への収載漏れの温床だった
|
|
1008
|
+
// (docs/static-wiring-dx-design.md §2-2)。
|
|
1009
|
+
const MODIFIER_PREVENT = 'prevent';
|
|
1010
|
+
const MODIFIER_STOP = 'stop';
|
|
1011
|
+
const MODIFIER_READONLY = 'ro';
|
|
1012
|
+
const MODIFIER_FLAGS = Object.freeze([
|
|
1013
|
+
MODIFIER_PREVENT, MODIFIER_STOP, MODIFIER_READONLY,
|
|
1014
|
+
]);
|
|
1015
|
+
const MODIFIER_KEY_INIT = 'init';
|
|
1016
|
+
const MODIFIER_KEY_SYNC = 'sync';
|
|
1017
|
+
const MODIFIER_KEYS = Object.freeze([
|
|
1018
|
+
MODIFIER_KEY_INIT, MODIFIER_KEY_SYNC,
|
|
1019
|
+
]);
|
|
1020
|
+
// bindingType 判別と左辺 namespace の語彙(単一正本)。manifest.syntax.bindingTypes で
|
|
1021
|
+
// 公開される。パーサ(parseBindTextsForElement)とイベント層はこの定数に分岐する。
|
|
1022
|
+
// apply 層のディスパッチマップ(apply/applyChange.ts の applyChangeByFirstSegment)の
|
|
1023
|
+
// キー集合との一致は __tests__/manifest.test.ts の drift テストが強制する —
|
|
1024
|
+
// manifest エントリ(DOM 非依存)から apply 層を import しないための分離。
|
|
1025
|
+
const ELSE_KEYWORD = 'else';
|
|
1026
|
+
const SPREAD_PROP = '...';
|
|
1027
|
+
const EVENT_PROP_PREFIX = 'on';
|
|
1028
|
+
const EVENT_TOKEN_NAMESPACE = 'eventToken';
|
|
1029
|
+
const COMMAND_NAMESPACE = 'command';
|
|
1030
|
+
const CLASS_NAMESPACE = 'class';
|
|
1031
|
+
const ATTR_NAMESPACE = 'attr';
|
|
1032
|
+
const STYLE_NAMESPACE = 'style';
|
|
1033
|
+
// リストインデックス参照名(`$1`..`$N`)の接頭辞(単一正本)。
|
|
1034
|
+
// manifest.syntax.indexParam で公開される。
|
|
1035
|
+
const INDEX_PARAM_PREFIX = '$';
|
|
848
1036
|
/**
|
|
849
1037
|
* stackIndexByIndexName
|
|
850
1038
|
* インデックス名からスタックインデックスへのマッピング
|
|
@@ -856,7 +1044,7 @@ const FILTER_SEPARATOR = '|'; // フィルタパイプの区切り
|
|
|
856
1044
|
*/
|
|
857
1045
|
const tmpIndexByIndexName = {};
|
|
858
1046
|
for (let i = 0; i < MAX_WILDCARD_DEPTH; i++) {
|
|
859
|
-
tmpIndexByIndexName[
|
|
1047
|
+
tmpIndexByIndexName[`${INDEX_PARAM_PREFIX}${i + 1}`] = i;
|
|
860
1048
|
}
|
|
861
1049
|
Object.freeze(tmpIndexByIndexName);
|
|
862
1050
|
const STATE_CONNECTED_CALLBACK_NAME = "$connectedCallback";
|
|
@@ -870,6 +1058,7 @@ const STATE_COMMAND_NAMESPACE_NAME = "$command";
|
|
|
870
1058
|
const STATE_EVENT_TOKENS_NAME = "$eventTokens";
|
|
871
1059
|
const STATE_ON_NAME = "$on";
|
|
872
1060
|
const STATE_STREAMS_NAME = "$streams";
|
|
1061
|
+
const STATE_WATCH_NAME = "$watch";
|
|
873
1062
|
const STATE_LIST_KEYS_NAME = "$listKeys";
|
|
874
1063
|
const STATE_STREAM_STATUS_NAMESPACE_NAME = "$streamStatus";
|
|
875
1064
|
const STATE_STREAM_ERROR_NAMESPACE_NAME = "$streamError";
|
|
@@ -907,6 +1096,27 @@ function getWcsManifest() {
|
|
|
907
1096
|
},
|
|
908
1097
|
// 正本 STRUCTURAL_BINDING_TYPE_SET から導出(手書きの二重定義を排除)。
|
|
909
1098
|
structuralDirectives: Array.from(STRUCTURAL_BINDING_TYPE_SET),
|
|
1099
|
+
modifiers: {
|
|
1100
|
+
flags: MODIFIER_FLAGS,
|
|
1101
|
+
keyValue: MODIFIER_KEYS,
|
|
1102
|
+
eventNamePrefix: EVENT_PROP_PREFIX,
|
|
1103
|
+
},
|
|
1104
|
+
indexParam: {
|
|
1105
|
+
prefix: INDEX_PARAM_PREFIX,
|
|
1106
|
+
maxDepth: MAX_WILDCARD_DEPTH,
|
|
1107
|
+
},
|
|
1108
|
+
bindingTypes: {
|
|
1109
|
+
elseKeyword: ELSE_KEYWORD,
|
|
1110
|
+
spread: SPREAD_PROP,
|
|
1111
|
+
eventPropertyPrefix: EVENT_PROP_PREFIX,
|
|
1112
|
+
propNamespaces: {
|
|
1113
|
+
eventToken: EVENT_TOKEN_NAMESPACE,
|
|
1114
|
+
command: COMMAND_NAMESPACE,
|
|
1115
|
+
class: CLASS_NAMESPACE,
|
|
1116
|
+
attr: ATTR_NAMESPACE,
|
|
1117
|
+
style: STYLE_NAMESPACE,
|
|
1118
|
+
},
|
|
1119
|
+
},
|
|
910
1120
|
},
|
|
911
1121
|
// 実装(Record のキー)から自動導出。手リストを持たない=ドリフトの構造的排除。
|
|
912
1122
|
filters: Object.keys(outputBuiltinFilters),
|
|
@@ -925,6 +1135,7 @@ function getWcsManifest() {
|
|
|
925
1135
|
STATE_EVENT_TOKENS_NAME,
|
|
926
1136
|
STATE_ON_NAME,
|
|
927
1137
|
STATE_STREAMS_NAME,
|
|
1138
|
+
STATE_WATCH_NAME,
|
|
928
1139
|
STATE_LIST_KEYS_NAME,
|
|
929
1140
|
STATE_STREAM_STATUS_NAMESPACE_NAME,
|
|
930
1141
|
STATE_STREAM_ERROR_NAMESPACE_NAME,
|
package/dist/parser.d.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
interface IPathInfo {
|
|
2
|
+
readonly id: number;
|
|
3
|
+
readonly path: string;
|
|
4
|
+
readonly segments: string[];
|
|
5
|
+
readonly lastSegment: string;
|
|
6
|
+
readonly cumulativePaths: string[];
|
|
7
|
+
readonly cumulativePathSet: Set<string>;
|
|
8
|
+
readonly cumulativePathInfos: IPathInfo[];
|
|
9
|
+
readonly cumulativePathInfoSet: Set<IPathInfo>;
|
|
10
|
+
readonly parentPath: string | null;
|
|
11
|
+
readonly parentPathInfo: IPathInfo | null;
|
|
12
|
+
readonly wildcardPaths: string[];
|
|
13
|
+
readonly wildcardPathSet: Set<string>;
|
|
14
|
+
readonly indexByWildcardPath: Record<string, number>;
|
|
15
|
+
readonly wildcardPathInfos: IPathInfo[];
|
|
16
|
+
readonly wildcardPathInfoSet: Set<IPathInfo>;
|
|
17
|
+
readonly wildcardParentPaths: string[];
|
|
18
|
+
readonly wildcardParentPathSet: Set<string>;
|
|
19
|
+
readonly wildcardParentPathInfos: IPathInfo[];
|
|
20
|
+
readonly wildcardParentPathInfoSet: Set<IPathInfo>;
|
|
21
|
+
readonly wildcardPositions: number[];
|
|
22
|
+
readonly lastWildcardPath: string | null;
|
|
23
|
+
readonly lastWildcardInfo: IPathInfo | null;
|
|
24
|
+
readonly wildcardCount: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Filter/types.ts
|
|
29
|
+
*
|
|
30
|
+
* Type definition file for filter functions.
|
|
31
|
+
*
|
|
32
|
+
* Main responsibilities:
|
|
33
|
+
* - Defines types for filter functions (FilterFn) and filter functions with options (FilterWithOptionsFn)
|
|
34
|
+
* - Type-safe management of filter name-to-function mappings (FilterWithOptions) and filter function arrays (Filters)
|
|
35
|
+
* - Defines types for retrieving filter functions from built-in filter collections
|
|
36
|
+
*
|
|
37
|
+
* Design points:
|
|
38
|
+
* - Type design enabling flexible filter design and extension
|
|
39
|
+
* - Supports filters with options and combinations of multiple filters
|
|
40
|
+
*/
|
|
41
|
+
type FilterFn<T = unknown> = (value: unknown) => T;
|
|
42
|
+
|
|
43
|
+
type BindingType = 'text' | 'prop' | 'event' | 'for' | 'if' | 'elseif' | 'else' | 'radio' | 'checkbox' | 'spread';
|
|
44
|
+
interface IFilterInfo {
|
|
45
|
+
readonly filterName: string;
|
|
46
|
+
readonly args: string[];
|
|
47
|
+
readonly filterFn: FilterFn;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* バインディング式のパース結果(DOM 非依存の部分)。`@wcstack/state/parser` の
|
|
51
|
+
* ParseBindTextResult がこれをそのまま公開するため、Node 等の DOM lib 型を
|
|
52
|
+
* ここに足してはならない(足すなら IBindingInfo 側へ)。
|
|
53
|
+
*/
|
|
54
|
+
interface IParsedBinding {
|
|
55
|
+
readonly propName: string;
|
|
56
|
+
readonly propSegments: string[];
|
|
57
|
+
readonly propModifiers: string[];
|
|
58
|
+
readonly statePathName: string;
|
|
59
|
+
readonly statePathInfo: IPathInfo;
|
|
60
|
+
readonly stateName: string;
|
|
61
|
+
readonly inFilters: IFilterInfo[];
|
|
62
|
+
readonly outFilters: IFilterInfo[];
|
|
63
|
+
readonly bindingType: BindingType;
|
|
64
|
+
readonly uuid?: string | null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
type ParseBindTextResult = IParsedBinding;
|
|
68
|
+
|
|
69
|
+
declare function parseBindTextsForElement(bindText: string): ParseBindTextResult[];
|
|
70
|
+
|
|
71
|
+
declare function getPathInfo(path: string): IPathInfo;
|
|
72
|
+
|
|
73
|
+
export { getPathInfo, parseBindTextsForElement };
|
|
74
|
+
export type { BindingType, IFilterInfo, IPathInfo, ParseBindTextResult };
|