@neeloong/form 0.10.0 → 0.12.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.md +15 -13
- package/index.d.mts +228 -82
- package/index.js +546 -423
- package/index.min.js +6 -6
- package/index.min.mjs +6 -6
- package/index.mjs +545 -422
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @neeloong/form v0.
|
|
2
|
+
* @neeloong/form v0.12.0
|
|
3
3
|
* (c) 2024-2025 Fierflame
|
|
4
4
|
* @license Apache-2.0
|
|
5
5
|
*/
|
|
@@ -651,7 +651,7 @@
|
|
|
651
651
|
|
|
652
652
|
}
|
|
653
653
|
/** @param {*} v */
|
|
654
|
-
const values
|
|
654
|
+
const values = v => {
|
|
655
655
|
if (!v || !Array.isArray(v)) { return null;}
|
|
656
656
|
const list = v.map(toValueItem).filter(valueFilter);
|
|
657
657
|
if (!list.length) { return null; }
|
|
@@ -726,7 +726,8 @@
|
|
|
726
726
|
/** @type {Record<string, {new(...p: ConstructorParameters<typeof Store>): Store}?>} */
|
|
727
727
|
let TypeStores = Object.create(null);
|
|
728
728
|
/**
|
|
729
|
-
* @
|
|
729
|
+
* @template [M=any]
|
|
730
|
+
* @param {Schema.Field<M>} schema
|
|
730
731
|
* @param {object} [options]
|
|
731
732
|
* @param {Store?} [options.parent]
|
|
732
733
|
* @param {string | number | null} [options.index]
|
|
@@ -863,6 +864,7 @@
|
|
|
863
864
|
/**
|
|
864
865
|
* 管理单个表单字段的状态和行为
|
|
865
866
|
* @template [T=any]
|
|
867
|
+
* @template [M=any]
|
|
866
868
|
*/
|
|
867
869
|
class Store {
|
|
868
870
|
/** @type {Map<string, Set<(value: any, store: any) => void | boolean | null>>} */
|
|
@@ -904,7 +906,8 @@
|
|
|
904
906
|
}
|
|
905
907
|
/**
|
|
906
908
|
* 从数据结构模式创建存储
|
|
907
|
-
* @
|
|
909
|
+
* @template [M=any]
|
|
910
|
+
* @param {Schema<M>} schema 数据结构模式
|
|
908
911
|
* @param {object} [options] 选项
|
|
909
912
|
* @param {boolean} [options.new] 是否为新建环境
|
|
910
913
|
*/
|
|
@@ -928,12 +931,12 @@
|
|
|
928
931
|
#ref = null;
|
|
929
932
|
get ref() { return this.#ref || createRef(this); }
|
|
930
933
|
/**
|
|
931
|
-
* @param {Schema.Field} schema 字段的 Schema 定义
|
|
934
|
+
* @param {Schema.Field<M>} schema 字段的 Schema 定义
|
|
932
935
|
* @param {object} [options] 可选配置
|
|
933
936
|
* @param {*} [options.parent]
|
|
934
937
|
* @param {*} [options.state]
|
|
935
938
|
* @param {number | string | null} [options.index]
|
|
936
|
-
* @param {number | Signal.State<number> | Signal.Computed<number>} [options.
|
|
939
|
+
* @param {number | Signal.State<number> | Signal.Computed<number>} [options.size]
|
|
937
940
|
* @param {boolean} [options.null]
|
|
938
941
|
* @param {boolean} [options.new]
|
|
939
942
|
* @param {boolean} [options.hidden]
|
|
@@ -968,9 +971,9 @@
|
|
|
968
971
|
null: isNull, state, ref,
|
|
969
972
|
setValue, setState, convert, onUpdate, onUpdateState,
|
|
970
973
|
validator, validators,
|
|
971
|
-
index,
|
|
974
|
+
index, size, new: isNew, parent: parentNode,
|
|
972
975
|
hidden, clearable, required, disabled, readonly,
|
|
973
|
-
label, description, placeholder, min, max, step, minLength, maxLength, pattern, values
|
|
976
|
+
label, description, placeholder, min, max, step, minLength, maxLength, pattern, values: values$1
|
|
974
977
|
} = {}) {
|
|
975
978
|
this.schema = schema;
|
|
976
979
|
this.#state.set(typeof state === 'object' && state || {});
|
|
@@ -1033,7 +1036,7 @@
|
|
|
1033
1036
|
[this.#selfMaxLength, this.#maxLength] = createState(this, number, maxLength, schema.maxLength);
|
|
1034
1037
|
[this.#selfPattern, this.#pattern] = createState(this, regex, pattern, schema.pattern);
|
|
1035
1038
|
// @ts-ignore
|
|
1036
|
-
[this.#selfValues, this.#values] = createState(this, values
|
|
1039
|
+
[this.#selfValues, this.#values] = createState(this, values, values$1, schema.values);
|
|
1037
1040
|
|
|
1038
1041
|
const validatorResult = createValidator(this, schema.validator, validator);
|
|
1039
1042
|
|
|
@@ -1048,10 +1051,10 @@
|
|
|
1048
1051
|
this.#cancelChange = cancelChange;
|
|
1049
1052
|
this.#cancelBlur = cancelBlur;
|
|
1050
1053
|
|
|
1051
|
-
if (
|
|
1052
|
-
this.#
|
|
1054
|
+
if (size instanceof exports.Signal.State || size instanceof exports.Signal.Computed) {
|
|
1055
|
+
this.#size = size;
|
|
1053
1056
|
} else {
|
|
1054
|
-
this.#
|
|
1057
|
+
this.#size = new exports.Signal.State(size || 0);
|
|
1055
1058
|
}
|
|
1056
1059
|
|
|
1057
1060
|
if (isNull) {
|
|
@@ -1089,7 +1092,7 @@
|
|
|
1089
1092
|
#root = this;
|
|
1090
1093
|
/** @readonly @type {any} */
|
|
1091
1094
|
#type;
|
|
1092
|
-
/** @readonly @type {
|
|
1095
|
+
/** @readonly @type {M | void} */
|
|
1093
1096
|
#meta;
|
|
1094
1097
|
/** @readonly @type {any} */
|
|
1095
1098
|
#component;
|
|
@@ -1107,9 +1110,9 @@
|
|
|
1107
1110
|
get component() { return this.#component; }
|
|
1108
1111
|
|
|
1109
1112
|
/** @type {Signal.State<number> | Signal.Computed<number>} */
|
|
1110
|
-
#
|
|
1113
|
+
#size;
|
|
1111
1114
|
/** 长度信息 */
|
|
1112
|
-
get
|
|
1115
|
+
get size() { return this.#size.get(); }
|
|
1113
1116
|
#index = new exports.Signal.State(/** @type {string | number} */(''));
|
|
1114
1117
|
/** 索引信息 */
|
|
1115
1118
|
get index() { return this.#index.get(); }
|
|
@@ -1291,10 +1294,10 @@
|
|
|
1291
1294
|
/** @readonly @type {Signal.Computed<(Schema.Value.Group | Schema.Value)[] | null>} */
|
|
1292
1295
|
#values
|
|
1293
1296
|
get selfValues() { return this.#selfValues.get(); }
|
|
1294
|
-
set selfValues(v) { this.#selfValues.set(values
|
|
1297
|
+
set selfValues(v) { this.#selfValues.set(values(v)); }
|
|
1295
1298
|
/** 可选值列表 */
|
|
1296
1299
|
get values() { return this.#values.get(); }
|
|
1297
|
-
set values(v) { this.#selfValues.set(values
|
|
1300
|
+
set values(v) { this.#selfValues.set(values(v)); }
|
|
1298
1301
|
|
|
1299
1302
|
|
|
1300
1303
|
/** @type {Signal.Computed<string[]>} */
|
|
@@ -1496,7 +1499,8 @@
|
|
|
1496
1499
|
|
|
1497
1500
|
/**
|
|
1498
1501
|
* @template {Record<string, any>} [T=Record<string, any>]
|
|
1499
|
-
* @
|
|
1502
|
+
* @template [M=any]
|
|
1503
|
+
* @extends {Store<T, M>}
|
|
1500
1504
|
*/
|
|
1501
1505
|
class ObjectStore extends Store {
|
|
1502
1506
|
get kind() { return 'object'; }
|
|
@@ -1510,7 +1514,7 @@
|
|
|
1510
1514
|
*/
|
|
1511
1515
|
child(key) { return this.#children[key] || null; }
|
|
1512
1516
|
/**
|
|
1513
|
-
* @param {Schema.Object & Schema.Attr} schema
|
|
1517
|
+
* @param {Schema.Object<M> & Schema.Attr<M>} schema
|
|
1514
1518
|
* @param {object} [options]
|
|
1515
1519
|
* @param {Store?} [options.parent]
|
|
1516
1520
|
* @param {number | string | null} [options.index]
|
|
@@ -1522,7 +1526,7 @@
|
|
|
1522
1526
|
const childrenTypes = Object.entries(schema.type);
|
|
1523
1527
|
super(schema, {
|
|
1524
1528
|
parent, index, new: isNew, onUpdate, onUpdateState,
|
|
1525
|
-
|
|
1529
|
+
size: childrenTypes.length,
|
|
1526
1530
|
setValue(v) { return typeof v === 'object' ? v : null; },
|
|
1527
1531
|
setState(v) { return typeof v === 'object' ? v : null; },
|
|
1528
1532
|
convert(v, state) {
|
|
@@ -1563,7 +1567,8 @@
|
|
|
1563
1567
|
|
|
1564
1568
|
/**
|
|
1565
1569
|
* @template [T=any]
|
|
1566
|
-
* @
|
|
1570
|
+
* @template [M=any]
|
|
1571
|
+
* @extends {Store<(T | null)[], M>}
|
|
1567
1572
|
*/
|
|
1568
1573
|
class ArrayStore extends Store {
|
|
1569
1574
|
/** @type {(index: number, isNew?: boolean) => Store} */
|
|
@@ -1586,7 +1591,7 @@
|
|
|
1586
1591
|
}
|
|
1587
1592
|
get kind() { return 'array'; }
|
|
1588
1593
|
/**
|
|
1589
|
-
* @param {Schema.Field} schema
|
|
1594
|
+
* @param {Schema.Field<M>} schema
|
|
1590
1595
|
* @param {object} [options]
|
|
1591
1596
|
* @param {Store?} [options.parent]
|
|
1592
1597
|
* @param {string | number | null} [options.index]
|
|
@@ -1604,6 +1609,7 @@
|
|
|
1604
1609
|
for (let i = children.length; i < length; i++) {
|
|
1605
1610
|
children.push(this.#create(i));
|
|
1606
1611
|
}
|
|
1612
|
+
children.length = length;
|
|
1607
1613
|
if (oldLength !== length) {
|
|
1608
1614
|
childrenState.set(children);
|
|
1609
1615
|
}
|
|
@@ -1611,7 +1617,7 @@
|
|
|
1611
1617
|
};
|
|
1612
1618
|
super(schema, {
|
|
1613
1619
|
index, new: isNew, parent,
|
|
1614
|
-
|
|
1620
|
+
size: new exports.Signal.Computed(() => childrenState.get().length),
|
|
1615
1621
|
state: [],
|
|
1616
1622
|
setValue(v) { return Array.isArray(v) ? v : v == null ? null : [v] },
|
|
1617
1623
|
setState(v) { return Array.isArray(v) ? v : v == null ? null : [v] },
|
|
@@ -1801,6 +1807,158 @@
|
|
|
1801
1807
|
// @ts-ignore
|
|
1802
1808
|
setArrayStore(ArrayStore);
|
|
1803
1809
|
|
|
1810
|
+
/** @import * as Layout from './index.mjs' */
|
|
1811
|
+
|
|
1812
|
+
/** @import { OldNode } from './createElement.mjs' */
|
|
1813
|
+
|
|
1814
|
+
/**
|
|
1815
|
+
* @param {(OldNode | string)[]} [layouts]
|
|
1816
|
+
* @returns {Layout.Child[]}
|
|
1817
|
+
*/
|
|
1818
|
+
function renderList(layouts) {
|
|
1819
|
+
if (!layouts?.length) { return []; }
|
|
1820
|
+
/** @type {Layout.Child[]} */
|
|
1821
|
+
const children = [];
|
|
1822
|
+
/** @type {[Layout.Node.Name | Layout.Node.Calc | Layout.Node.Value | null, OldNode][]} */
|
|
1823
|
+
let ifList = [];
|
|
1824
|
+
/** @type {Record<string, Layout.Template>} */
|
|
1825
|
+
let templates = Object.create(null);
|
|
1826
|
+
let hasTemplate = false;
|
|
1827
|
+
for (const layout of layouts) {
|
|
1828
|
+
if (typeof layout === 'string') { continue; }
|
|
1829
|
+
const name = layout.template;
|
|
1830
|
+
if (!name) { continue; }
|
|
1831
|
+
hasTemplate = true;
|
|
1832
|
+
const children = convertItem(layout);
|
|
1833
|
+
templates[name] = { params: layout.params, children: children ? [children] : [] };
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
/** @param {[Layout.Node.Name | Layout.Node.Calc | Layout.Node.Value | null, OldNode][]} list */
|
|
1837
|
+
function renderIf(list) {
|
|
1838
|
+
if (!list.length) { return; }
|
|
1839
|
+
children.push({
|
|
1840
|
+
type: 'divergent',
|
|
1841
|
+
children: list.map(([a, b]) => {
|
|
1842
|
+
const child = convertItem(b);
|
|
1843
|
+
if (!child) { return [{ children: [] }, a]; }
|
|
1844
|
+
if (typeof child !== 'string' && child.type === 'fragment') {
|
|
1845
|
+
return [child, a];
|
|
1846
|
+
}
|
|
1847
|
+
return [{ children: [child] }, a];
|
|
1848
|
+
}),
|
|
1849
|
+
});
|
|
1850
|
+
}
|
|
1851
|
+
for (const layout of layouts) {
|
|
1852
|
+
if (typeof layout === 'string') {
|
|
1853
|
+
renderIf(ifList);
|
|
1854
|
+
ifList = [];
|
|
1855
|
+
children.push(layout);
|
|
1856
|
+
continue;
|
|
1857
|
+
}
|
|
1858
|
+
if (layout.template) {
|
|
1859
|
+
renderIf(ifList);
|
|
1860
|
+
ifList = [];
|
|
1861
|
+
continue;
|
|
1862
|
+
}
|
|
1863
|
+
if (ifList.length && layout.else) {
|
|
1864
|
+
const ifv = layout.if || null;
|
|
1865
|
+
ifList.push([ifv, layout]);
|
|
1866
|
+
if (!ifv) {
|
|
1867
|
+
renderIf(ifList);
|
|
1868
|
+
ifList = [];
|
|
1869
|
+
}
|
|
1870
|
+
continue;
|
|
1871
|
+
}
|
|
1872
|
+
renderIf(ifList);
|
|
1873
|
+
ifList = [];
|
|
1874
|
+
const ifv = layout.if;
|
|
1875
|
+
if (ifv) {
|
|
1876
|
+
ifList.push([ifv, layout]);
|
|
1877
|
+
continue;
|
|
1878
|
+
}
|
|
1879
|
+
const s = convertItem(layout);
|
|
1880
|
+
if (s)
|
|
1881
|
+
children.push(s);
|
|
1882
|
+
}
|
|
1883
|
+
renderIf(ifList);
|
|
1884
|
+
if (hasTemplate) {
|
|
1885
|
+
return [{ type: 'fragment', templates, children }];
|
|
1886
|
+
}
|
|
1887
|
+
return children;
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1890
|
+
|
|
1891
|
+
/**
|
|
1892
|
+
* @param {OldNode} layout
|
|
1893
|
+
* @returns {Layout.Child | undefined}
|
|
1894
|
+
*/
|
|
1895
|
+
function renderFillDirectives$1({ text, html }) {
|
|
1896
|
+
if (text != null) { return { type: 'content', value: text }; }
|
|
1897
|
+
if (html != null) { return { type: 'content', value: html, html: true }; }
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1900
|
+
/**
|
|
1901
|
+
* @param {OldNode} layout
|
|
1902
|
+
* @returns {Layout.Child?}
|
|
1903
|
+
*/
|
|
1904
|
+
function convertNode(layout) {
|
|
1905
|
+
const fragment = layout.fragment;
|
|
1906
|
+
if (fragment && typeof fragment === 'string') {
|
|
1907
|
+
return { type: 'template', template: fragment, attrs: layout.attrs, children: [] };
|
|
1908
|
+
}
|
|
1909
|
+
const child = renderFillDirectives$1(layout);
|
|
1910
|
+
const children = child ? [child] : renderList(layout.children);
|
|
1911
|
+
if (!layout.name || fragment) { return child || { type: 'fragment', children }; }
|
|
1912
|
+
return {
|
|
1913
|
+
name: layout.name,
|
|
1914
|
+
is: layout.is,
|
|
1915
|
+
attrs: layout.attrs,
|
|
1916
|
+
events: layout.events,
|
|
1917
|
+
classes: layout.classes,
|
|
1918
|
+
styles: layout.styles,
|
|
1919
|
+
enhancements: layout.enhancements,
|
|
1920
|
+
bind: layout.bind,
|
|
1921
|
+
comment: layout.comment,
|
|
1922
|
+
children,
|
|
1923
|
+
};
|
|
1924
|
+
}
|
|
1925
|
+
/**
|
|
1926
|
+
*
|
|
1927
|
+
* @param {OldNode} layout
|
|
1928
|
+
* @returns {Layout.Child?}
|
|
1929
|
+
*/
|
|
1930
|
+
function convertItem(layout) {
|
|
1931
|
+
let child = convertNode(layout);
|
|
1932
|
+
/** @type {Layout.Variable[]?} */
|
|
1933
|
+
let vars = layout.vars;
|
|
1934
|
+
if (vars.length && child && typeof child !== 'string') {
|
|
1935
|
+
if (child.vars) {
|
|
1936
|
+
child.vars = [...vars, ...child.vars];
|
|
1937
|
+
} else if (child) {
|
|
1938
|
+
child.vars = vars;
|
|
1939
|
+
} else {
|
|
1940
|
+
child = { type: 'fragment', vars, children: [] };
|
|
1941
|
+
}
|
|
1942
|
+
vars = null;
|
|
1943
|
+
}
|
|
1944
|
+
const enumValue = layout.enum;
|
|
1945
|
+
const name = layout.value;
|
|
1946
|
+
if (enumValue) { child = { type: 'enum', value: enumValue, vars, children: child ? [child] : [] }; vars = null; }
|
|
1947
|
+
if (name) { child = { type: 'value', name, vars, children: child ? [child] : [] }; vars = null; }
|
|
1948
|
+
if (vars?.length) {
|
|
1949
|
+
child = { type: 'fragment', vars, children: child ? [child] : [] };
|
|
1950
|
+
}
|
|
1951
|
+
return child;
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
/**
|
|
1955
|
+
* @param {(OldNode | string)[]} layouts 布局信息
|
|
1956
|
+
* @returns {Layout.Child[]}
|
|
1957
|
+
*/
|
|
1958
|
+
function convert(layouts) {
|
|
1959
|
+
return renderList(layouts);
|
|
1960
|
+
}
|
|
1961
|
+
|
|
1804
1962
|
const numRegex = /^([+-]?(\d(_?\d)*(\.(\d(_?\d)*)?)?|\.\d(_?\d)*)(?:e[+-]?\d(_?\d)*)|0(b[01](?:_?[01])*|o[0-7](?:_?[0-7])*|x[\dA-F](?:_?[\dA-F])*))$/is;
|
|
1805
1963
|
/**
|
|
1806
1964
|
*
|
|
@@ -1856,6 +2014,7 @@
|
|
|
1856
2014
|
}
|
|
1857
2015
|
|
|
1858
2016
|
/** @import * as Layout from './index.mjs' */
|
|
2017
|
+
/** @import { OldNode } from './createElement.mjs' */
|
|
1859
2018
|
|
|
1860
2019
|
const attrPattern = /^(?<decorator>[:@!+*\.?]|style:|样式:)?(?<name>-?[\w\p{Unified_Ideograph}_][-\w\p{Unified_Ideograph}_:\d\.]*)$/u;
|
|
1861
2020
|
const enhancementPattern = /^~(?<enhancement>[\w\p{Unified_Ideograph}_][-\w\p{Unified_Ideograph}_\d\.]*)(?:(?<decorator>[:@!])(?<name>-?[\w\p{Unified_Ideograph}_][-\w\p{Unified_Ideograph}_:\d\.]*))?$/u;
|
|
@@ -1895,14 +2054,14 @@
|
|
|
1895
2054
|
}
|
|
1896
2055
|
|
|
1897
2056
|
/**
|
|
1898
|
-
* @param {
|
|
2057
|
+
* @param {OldNode} node
|
|
1899
2058
|
* @param {Exclude<Layout.Options['createCalc'], undefined>} createCalc
|
|
1900
2059
|
* @param {Exclude<Layout.Options['createInit'], undefined>} createInit
|
|
1901
2060
|
* @param {Exclude<Layout.Options['createEvent'], undefined>} createEvent
|
|
1902
2061
|
* @param {boolean} enableHTML
|
|
1903
2062
|
*/
|
|
1904
2063
|
function createAttributeAdder(node, createCalc, createInit, createEvent, enableHTML) {
|
|
1905
|
-
const { attrs, events, classes, styles, vars,
|
|
2064
|
+
const { attrs, events, classes, styles, vars, params, enhancements } = node;
|
|
1906
2065
|
/**
|
|
1907
2066
|
* @param {string} qName
|
|
1908
2067
|
* @param {string} value
|
|
@@ -1957,11 +2116,11 @@
|
|
|
1957
2116
|
return;
|
|
1958
2117
|
}
|
|
1959
2118
|
if (decorator === '+') {
|
|
1960
|
-
vars
|
|
2119
|
+
vars.push({...value ? parse$1(value, createInit) : {value: undefined}, variable: name, init: true});
|
|
1961
2120
|
return;
|
|
1962
2121
|
}
|
|
1963
2122
|
if (decorator === '*') {
|
|
1964
|
-
|
|
2123
|
+
vars.push({...parse$1(value, createCalc), variable: name, init: false });
|
|
1965
2124
|
return;
|
|
1966
2125
|
}
|
|
1967
2126
|
if (decorator === '?') {
|
|
@@ -1998,10 +2157,40 @@
|
|
|
1998
2157
|
|
|
1999
2158
|
/** @import * as Layout from './index.mjs' */
|
|
2000
2159
|
|
|
2160
|
+
/**
|
|
2161
|
+
* @typedef {object} OldNode 布局节点
|
|
2162
|
+
* @property {string} name 标签名
|
|
2163
|
+
* @property {string?} [is]
|
|
2164
|
+
* @property {string} [id]
|
|
2165
|
+
* @property {Record<string, Layout.Node.Name | Layout.Node.Calc | Layout.Node.Value>} attrs 属性
|
|
2166
|
+
* @property {Record<string, Layout.Node.Name | Layout.Node.Calc | Layout.Node.Value>} params 模板参数定义
|
|
2167
|
+
* @property {Record<string, Layout.Node.Name | Layout.Node.Calc | Layout.Node.Value>} classes 类名
|
|
2168
|
+
* @property {Record<string, Layout.Node.Name | Layout.Node.Calc | Layout.Node.Value>} styles 样式
|
|
2169
|
+
* @property {Record<string, Layout.Node.Name | Layout.Node.Event>} events 事件
|
|
2170
|
+
* @property {Layout.Variable[]} vars 局部变量/别名/计算名
|
|
2171
|
+
* @property {Record<string, Layout.Enhancement>} enhancements 增强
|
|
2172
|
+
*
|
|
2173
|
+
* @property {string} [template] 模板定义的名称
|
|
2174
|
+
* @property {boolean | string} [fragment] 是否为片段或模板调用
|
|
2175
|
+
*
|
|
2176
|
+
* @property {Layout.Node.Name | Layout.Node.Calc | Layout.Node.Value} [if] 分歧条件
|
|
2177
|
+
* @property {boolean} [else] 否定
|
|
2178
|
+
*
|
|
2179
|
+
* @property {string} [value] 值关联
|
|
2180
|
+
* @property {Layout.Node.Name | Layout.Node.Calc | Layout.Node.Value} [enum] 列表属性枚举
|
|
2181
|
+
*
|
|
2182
|
+
* @property {boolean | string} [bind] 绑定内容
|
|
2183
|
+
* @property {Layout.Node.Name | Layout.Node.Value | Layout.Node.Calc} [text] 文本渲染
|
|
2184
|
+
* @property {Layout.Node.Name | Layout.Node.Value | Layout.Node.Calc} [html] HTML 渲染
|
|
2185
|
+
*
|
|
2186
|
+
* @property {string} [comment] 注释
|
|
2187
|
+
*
|
|
2188
|
+
* @property {(OldNode | string)[]} children 子元素
|
|
2189
|
+
*/
|
|
2001
2190
|
/**
|
|
2002
2191
|
* @param {string} name
|
|
2003
2192
|
* @param {string?} [is]
|
|
2004
|
-
* @returns {
|
|
2193
|
+
* @returns {OldNode}
|
|
2005
2194
|
*
|
|
2006
2195
|
*/
|
|
2007
2196
|
function createElement(name, is) {
|
|
@@ -2013,8 +2202,7 @@
|
|
|
2013
2202
|
events: Object.create(null),
|
|
2014
2203
|
classes: Object.create(null),
|
|
2015
2204
|
styles: Object.create(null),
|
|
2016
|
-
vars:
|
|
2017
|
-
aliases: Object.create(null),
|
|
2205
|
+
vars: [],
|
|
2018
2206
|
params: Object.create(null),
|
|
2019
2207
|
enhancements: Object.create(null),
|
|
2020
2208
|
};
|
|
@@ -2267,6 +2455,7 @@
|
|
|
2267
2455
|
};
|
|
2268
2456
|
|
|
2269
2457
|
/** @import * as Layout from './index.mjs' */
|
|
2458
|
+
/** @import { OldNode } from './createElement.mjs' */
|
|
2270
2459
|
|
|
2271
2460
|
const tagNamePattern = /^(?<name>[\w\p{Unified_Ideograph}_][-\.\|:|d\w\p{Unified_Ideograph}_:]*)(?:|(?<is>[\w\p{Unified_Ideograph}_][-\.\|:|d\w\p{Unified_Ideograph}_]*))?$/u;
|
|
2272
2461
|
|
|
@@ -2332,7 +2521,7 @@
|
|
|
2332
2521
|
* 解析模板内容
|
|
2333
2522
|
* @param {string} source 输入源字符串
|
|
2334
2523
|
* @param {Layout.Options} [options] 解析选项
|
|
2335
|
-
* @returns {
|
|
2524
|
+
* @returns {Layout.Child[]}
|
|
2336
2525
|
*/
|
|
2337
2526
|
function parse(source, {
|
|
2338
2527
|
createCalc = () => { throw new ParseError('CALC'); },
|
|
@@ -2341,15 +2530,15 @@
|
|
|
2341
2530
|
simpleTag = new Set,
|
|
2342
2531
|
enableHTML = false,
|
|
2343
2532
|
} = {}) {
|
|
2344
|
-
/** @type {(
|
|
2533
|
+
/** @type {(OldNode | string)[]} */
|
|
2345
2534
|
const children = [];
|
|
2346
2535
|
|
|
2347
2536
|
const doc = { children };
|
|
2348
|
-
/** @type {(
|
|
2537
|
+
/** @type {(OldNode | null)[]} */
|
|
2349
2538
|
const stack = [];
|
|
2350
|
-
/** @type {
|
|
2539
|
+
/** @type {OldNode?} */
|
|
2351
2540
|
let currentNode = null;
|
|
2352
|
-
/** @type {typeof doc |
|
|
2541
|
+
/** @type {typeof doc | OldNode} */
|
|
2353
2542
|
let current = doc;
|
|
2354
2543
|
function endElement() {
|
|
2355
2544
|
currentNode = stack.pop() || null;
|
|
@@ -2525,229 +2714,156 @@
|
|
|
2525
2714
|
endElement();
|
|
2526
2715
|
}
|
|
2527
2716
|
}
|
|
2528
|
-
return children;
|
|
2717
|
+
return convert(children);
|
|
2529
2718
|
}
|
|
2530
2719
|
|
|
2531
|
-
/** @import * as Layout from './index.mjs' */
|
|
2532
|
-
|
|
2533
2720
|
/**
|
|
2534
|
-
*
|
|
2535
|
-
* @
|
|
2536
|
-
* @
|
|
2721
|
+
* @typedef {object} Enhancement 增强信息
|
|
2722
|
+
* @property {Record<string, Node.Name | Node.Event>} events 事件
|
|
2723
|
+
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} attrs 属性
|
|
2724
|
+
* @property {Node.Name | Node.Calc | Node.Value} [value] 主值
|
|
2725
|
+
* @property {boolean | string} [bind] 绑定信息
|
|
2537
2726
|
*/
|
|
2538
|
-
function _xmlEncoder(c) {
|
|
2539
|
-
return c == '<' && '<' ||
|
|
2540
|
-
c == '>' && '>' ||
|
|
2541
|
-
c == '&' && '&' ||
|
|
2542
|
-
c == '"' && '"' ||
|
|
2543
|
-
'&#' + c.charCodeAt() + ';';
|
|
2544
|
-
}
|
|
2545
2727
|
|
|
2546
2728
|
/**
|
|
2547
|
-
* @
|
|
2729
|
+
* @typedef {object} Options 解析选项
|
|
2730
|
+
* @property {boolean} [enableHTML] 启用 `!html` 指令
|
|
2731
|
+
* @property {(t: string) => Calc} [createCalc] 创建计算属性的工厂函数
|
|
2732
|
+
* @property {(t: string) => Calc} [createInit] 创建变量初始化的工厂函数
|
|
2733
|
+
* @property {(t: string) => EventListener} [createEvent] 创建事件监听器的工厂函数
|
|
2734
|
+
* @property {Set<string>} [simpleTag] 简单标签的集合
|
|
2735
|
+
*/
|
|
2736
|
+
/**
|
|
2737
|
+
* @template [T=any]
|
|
2738
|
+
* @typedef {{value: T; name?: undefined; calc?: undefined; event?: undefined}} Node.Value 基础值
|
|
2548
2739
|
*/
|
|
2549
|
-
function toValue({name, calc, event, value}) {
|
|
2550
|
-
if (value === true || value === undefined) { return ''; }
|
|
2551
|
-
const val = typeof value === 'string' ? JSON.stringify(value) : name || calc || event || value;
|
|
2552
|
-
return `="${toAttrValue$1(val)}"`;
|
|
2553
|
-
}
|
|
2554
2740
|
/**
|
|
2555
|
-
* @
|
|
2741
|
+
* @typedef {{name: string; value?: undefined; calc?: undefined; event?: undefined}} Node.Name 名称
|
|
2742
|
+
*/
|
|
2743
|
+
/**
|
|
2744
|
+
* @typedef {{event: EventListener; name?: undefined; calc?: undefined; value?: undefined}} Node.Event 事件
|
|
2556
2745
|
*/
|
|
2557
|
-
function toAttrValue$1(value) {
|
|
2558
|
-
return String(value).replace(/[<&"]/g, _xmlEncoder);
|
|
2559
|
-
}
|
|
2560
|
-
|
|
2561
2746
|
/**
|
|
2562
|
-
* @
|
|
2563
|
-
* @param {string} [prefix]
|
|
2564
|
-
* @param {boolean | null} [isName]
|
|
2747
|
+
* @typedef {{calc: Calc; name?: undefined; value?: undefined; event?: undefined}} Node.Calc 计算
|
|
2565
2748
|
*/
|
|
2566
|
-
function *values(values, prefix, isName = false) {
|
|
2567
|
-
if (prefix) {
|
|
2568
|
-
for (const [key, {name, calc, event, value}] of Object.entries(values)) {
|
|
2569
|
-
yield ` ${prefix}${key}`;
|
|
2570
|
-
if (isName && name === key) { continue; }
|
|
2571
|
-
const val = value && typeof value === 'string' ? JSON.stringify(value) : name || calc || event || value;
|
|
2572
|
-
if (val == null) { continue; }
|
|
2573
|
-
if (isName === false && val === true) { continue; }
|
|
2574
|
-
yield `="${toAttrValue$1(val)}"`;
|
|
2575
|
-
}
|
|
2576
|
-
return;
|
|
2577
|
-
}
|
|
2578
|
-
for (const [key, attr] of Object.entries(values)) {
|
|
2579
|
-
if (!attr) { continue; }
|
|
2580
|
-
const {name, value, calc} = attr;
|
|
2581
|
-
if (name === key) { yield ` :${key}`; continue; }
|
|
2582
|
-
if (name || calc || typeof value !== 'string') {
|
|
2583
|
-
yield ` :${key}="${toAttrValue$1(name || calc || value)}"`;
|
|
2584
|
-
continue;
|
|
2585
|
-
}
|
|
2586
|
-
yield ` ${key}`;
|
|
2587
|
-
if (value) {
|
|
2588
|
-
yield `="${toAttrValue$1(value)}"`;
|
|
2589
|
-
}
|
|
2590
|
-
}
|
|
2591
|
-
}
|
|
2592
|
-
|
|
2593
2749
|
|
|
2594
2750
|
/**
|
|
2595
2751
|
*
|
|
2596
|
-
* @
|
|
2597
|
-
* @param {number} [level]
|
|
2598
|
-
* @returns {Iterable<string>}
|
|
2752
|
+
* @typedef {Divergent | Select | Enum | Content | CallTemplate | Fragment | Node | string} Child 分歧
|
|
2599
2753
|
*/
|
|
2600
|
-
function* nodeToString(node, level = 0) {
|
|
2601
|
-
const { children, is, name } = node;
|
|
2602
|
-
const pad = level > 0 ? ''.padEnd(level, '\t') : '';
|
|
2603
|
-
|
|
2604
|
-
yield pad;
|
|
2605
|
-
yield* ['<', name || '-'];
|
|
2606
|
-
if (is) { yield* ['|', is]; }
|
|
2607
|
-
if (node.template) {
|
|
2608
|
-
yield ` !template="${toAttrValue$1(node.template)}"`;
|
|
2609
|
-
yield* values(node.params, '?', null);
|
|
2610
|
-
}
|
|
2611
|
-
if (node.fragment) { yield node.fragment === true ? ` !fragment` : ` !fragment="${toAttrValue$1(node.fragment)}"`; }
|
|
2612
|
-
if (node.else) { yield ` !else`; }
|
|
2613
|
-
if (node.if) { yield ` !if${toValue(node.if)}`; }
|
|
2614
|
-
if (node.value) { yield ` !value="${toAttrValue$1(node.value)}"`; }
|
|
2615
|
-
if (node.enum) { yield ` !enum${toValue(node.enum)}`; }
|
|
2616
|
-
yield* values(node.aliases, '*', null);
|
|
2617
|
-
yield* values(node.vars, '+', null);
|
|
2618
|
-
if (node.bind) { yield node.bind === true ? ` !bind` : ` !bind="${toAttrValue$1(node.bind)}"`; }
|
|
2619
|
-
yield* values(node.attrs);
|
|
2620
|
-
yield* values(node.events, '@', true);
|
|
2621
|
-
yield* values(node.classes, '.', true);
|
|
2622
|
-
yield* values(node.styles, 'style:');
|
|
2623
|
-
for (const [k, en] of Object.entries(node.enhancements)) {
|
|
2624
|
-
if (en.bind) { yield en.bind === true ? ` ~${k}!bind` : ` ~${k}!bind="${toAttrValue$1(en.bind)}"`; }
|
|
2625
|
-
if (en.value) { yield ` ~${k}${toValue(en.value)}`; }
|
|
2626
|
-
yield* values(en.attrs, `~${k}:`, true);
|
|
2627
|
-
yield* values(en.events, `~${k}@`, true);
|
|
2628
|
-
}
|
|
2629
|
-
if (node.text) { yield ` !text${toValue(node.text)}`; }
|
|
2630
|
-
if (node.html) { yield ` !html${toValue(node.html)}`; }
|
|
2631
|
-
if (node.comment) { yield ` !comment="${toAttrValue$1(node.comment)}"`; }
|
|
2632
|
-
if (!children.length) {
|
|
2633
|
-
yield '/>';
|
|
2634
|
-
if (level >= 0) { yield '\n'; }
|
|
2635
|
-
return;
|
|
2636
|
-
}
|
|
2637
|
-
if (children.length === 1) {
|
|
2638
|
-
const [child] = children;
|
|
2639
|
-
if (typeof child === 'string' && child.length < 80 && !child.includes('\n')) {
|
|
2640
|
-
yield '>';
|
|
2641
|
-
yield* [child.replace(/[<&\t]/g, _xmlEncoder).replace(/]]>/g, ']]>')];
|
|
2642
|
-
yield* ['</', name, '>'];
|
|
2643
|
-
if (level >= 0) { yield '\n'; }
|
|
2644
|
-
return;
|
|
2645
|
-
}
|
|
2646
|
-
}
|
|
2647
|
-
yield '>';
|
|
2648
|
-
if (level >= 0) { yield '\n'; }
|
|
2649
|
-
yield* listToString(children, level >= 0 ? level + 1 : -1);
|
|
2650
|
-
yield* [pad, '</', name, '>'];
|
|
2651
|
-
if (level >= 0) { yield '\n'; }
|
|
2652
|
-
|
|
2653
|
-
}
|
|
2654
2754
|
/**
|
|
2655
2755
|
*
|
|
2656
|
-
* @
|
|
2657
|
-
* @
|
|
2658
|
-
* @
|
|
2756
|
+
* @template [T=unknown]
|
|
2757
|
+
* @typedef {object} Variable 变量定义
|
|
2758
|
+
* @property {string} variable
|
|
2759
|
+
* @property {string} [name]
|
|
2760
|
+
* @property {Calc} [calc]
|
|
2761
|
+
* @property {T} [value]
|
|
2762
|
+
* @property {boolean} [init] 是否普通变量
|
|
2763
|
+
* @property {string} [comment] 注释
|
|
2659
2764
|
*/
|
|
2660
|
-
function* listToString(nodes, level = 0) {
|
|
2661
|
-
if (!nodes.length) { return ''; }
|
|
2662
|
-
|
|
2663
|
-
const pad = level > 0 ? ''.padEnd(level, '\t') : '';
|
|
2664
|
-
for (const child of nodes) {
|
|
2665
|
-
if (typeof child === 'string') {
|
|
2666
|
-
let text = child.replace(/[<&\t]/g, _xmlEncoder).replace(/]]>/g, ']]>');
|
|
2667
|
-
if (pad) {
|
|
2668
|
-
text = text.replace(/(?<=^|\n)/g, pad);
|
|
2669
|
-
}
|
|
2670
|
-
yield text;
|
|
2671
|
-
if (level >= 0) { yield '\n'; }
|
|
2672
|
-
} else {
|
|
2673
|
-
yield* nodeToString(child, level);
|
|
2674
|
-
}
|
|
2675
|
-
}
|
|
2676
|
-
}
|
|
2677
2765
|
/**
|
|
2678
|
-
*
|
|
2679
|
-
* @
|
|
2680
|
-
* @
|
|
2681
|
-
* @
|
|
2766
|
+
* @typedef {object} Template
|
|
2767
|
+
* @property {Variable[]?} [vars] 局部变量/别名/计算名
|
|
2768
|
+
* @property {Record<string, Template>} [templates]
|
|
2769
|
+
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} params 模板参数定义
|
|
2770
|
+
* @property {Child[]} children 子元素
|
|
2771
|
+
* @property {string} [comment] 注释
|
|
2682
2772
|
*/
|
|
2683
|
-
function stringify(value, formable) {
|
|
2684
|
-
const level = formable ? 0 : -1;
|
|
2685
|
-
if (Array.isArray(value)) { return [...listToString(value, level)].join(''); }
|
|
2686
|
-
return [nodeToString(value, level)].join();
|
|
2687
|
-
|
|
2688
|
-
}
|
|
2689
|
-
|
|
2690
2773
|
/**
|
|
2691
|
-
*
|
|
2692
|
-
* @
|
|
2693
|
-
* @property {
|
|
2694
|
-
* @property {
|
|
2695
|
-
* @property {
|
|
2774
|
+
*
|
|
2775
|
+
* @typedef {object} DivergentChildren 分歧项
|
|
2776
|
+
* @property {Variable[]?} [vars] 局部变量/别名/计算名
|
|
2777
|
+
* @property {Record<string, Template>} [templates]
|
|
2778
|
+
* @property {Child[]} children 子元素
|
|
2779
|
+
* @property {string} [comment] 注释
|
|
2696
2780
|
*/
|
|
2697
|
-
|
|
2698
2781
|
/**
|
|
2699
|
-
*
|
|
2700
|
-
* @
|
|
2701
|
-
* @property {
|
|
2702
|
-
* @property {
|
|
2703
|
-
* @property {
|
|
2704
|
-
* @property {
|
|
2782
|
+
*
|
|
2783
|
+
* @typedef {object} Divergent 分歧
|
|
2784
|
+
* @property {Variable[]?} [vars] 局部变量/别名/计算名
|
|
2785
|
+
* @property {Record<string, Template>} [templates]
|
|
2786
|
+
* @property {'divergent'} type
|
|
2787
|
+
* @property {[children: DivergentChildren, condition?: Node.Name | Node.Calc | Node.Value | null][]} children
|
|
2788
|
+
* @property {string} [comment] 注释
|
|
2705
2789
|
*/
|
|
2706
2790
|
/**
|
|
2707
|
-
*
|
|
2708
|
-
* @typedef {
|
|
2791
|
+
*
|
|
2792
|
+
* @typedef {object} Select 选值
|
|
2793
|
+
* @property {Variable[]?} [vars] 局部变量/别名/计算名
|
|
2794
|
+
* @property {Record<string, Template>} [templates]
|
|
2795
|
+
* @property {'value'} type
|
|
2796
|
+
* @property {string} name
|
|
2797
|
+
* @property {Child[]} children 子元素
|
|
2798
|
+
* @property {string} [comment] 注释
|
|
2709
2799
|
*/
|
|
2710
2800
|
/**
|
|
2711
|
-
*
|
|
2801
|
+
*
|
|
2802
|
+
* @typedef {object} Enum 枚举
|
|
2803
|
+
* @property {Variable[]?} [vars] 局部变量/别名/计算名
|
|
2804
|
+
* @property {Record<string, Template>} [templates]
|
|
2805
|
+
* @property {'enum'} type
|
|
2806
|
+
* @property {Node.Name | Node.Calc | Node.Value} value
|
|
2807
|
+
* @property {Child[]} children 子元素
|
|
2808
|
+
* @property {string} [comment] 注释
|
|
2712
2809
|
*/
|
|
2713
2810
|
/**
|
|
2714
|
-
*
|
|
2811
|
+
*
|
|
2812
|
+
* @typedef {object} Content 内容填充
|
|
2813
|
+
* @property {Variable[]?} [vars] 局部变量/别名/计算名
|
|
2814
|
+
* @property {Record<string, Template>} [templates]
|
|
2815
|
+
* @property {'content'} type
|
|
2816
|
+
* @property {Node.Name | Node.Calc | Node.Value} value
|
|
2817
|
+
* @property {boolean} [html]
|
|
2818
|
+
* @property {string} [comment] 注释
|
|
2715
2819
|
*/
|
|
2716
2820
|
/**
|
|
2717
|
-
*
|
|
2821
|
+
*
|
|
2822
|
+
* @typedef {object} CallTemplate 模板调用
|
|
2823
|
+
* @property {Variable[]?} [vars] 局部变量/别名/计算名
|
|
2824
|
+
* @property {Record<string, Template>} [templates]
|
|
2825
|
+
* @property {'template'} type
|
|
2826
|
+
* @property {string} template 模板名
|
|
2827
|
+
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} attrs 属性
|
|
2828
|
+
* @property {boolean | string} [bind] 绑定内容
|
|
2829
|
+
* @property {Child[]} children 子元素
|
|
2830
|
+
* @property {string} [comment] 注释
|
|
2831
|
+
*/
|
|
2832
|
+
|
|
2833
|
+
/**
|
|
2834
|
+
* @typedef {object} Fragment 片段
|
|
2835
|
+
* @property {Variable[]?} [vars] 局部变量/别名/计算名
|
|
2836
|
+
* @property {Record<string, Template>} [templates]
|
|
2837
|
+
* @property {'fragment'} type
|
|
2838
|
+
* @property {Child[]} children 子元素
|
|
2839
|
+
* @property {string} [comment] 注释
|
|
2718
2840
|
*/
|
|
2841
|
+
|
|
2842
|
+
|
|
2719
2843
|
/**
|
|
2720
2844
|
* @typedef {object} Node 布局节点
|
|
2845
|
+
* @property {Variable[]?} [vars] 局部变量/别名/计算名
|
|
2846
|
+
* @property {Record<string, Template>} [templates]
|
|
2847
|
+
* @property {null} [type]
|
|
2848
|
+
*
|
|
2721
2849
|
* @property {string} name 标签名
|
|
2722
2850
|
* @property {string?} [is]
|
|
2723
2851
|
* @property {string} [id]
|
|
2724
2852
|
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} attrs 属性
|
|
2725
|
-
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} params 模板参数定义
|
|
2726
2853
|
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} classes 类名
|
|
2727
2854
|
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} styles 样式
|
|
2728
2855
|
* @property {Record<string, Node.Name | Node.Event>} events 事件
|
|
2729
|
-
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} vars 局部变量
|
|
2730
|
-
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} aliases 别名/计算名
|
|
2731
2856
|
* @property {Record<string, Enhancement>} enhancements 增强
|
|
2732
2857
|
*
|
|
2733
|
-
* @property {string} [template] 模板定义的名称
|
|
2734
|
-
* @property {boolean | string} [fragment] 是否为片段或模板调用
|
|
2735
|
-
*
|
|
2736
|
-
* @property {Node.Name | Node.Calc | Node.Value} [if] 分歧条件
|
|
2737
|
-
* @property {boolean} [else] 否定
|
|
2738
|
-
*
|
|
2739
|
-
* @property {string} [value] 值关联
|
|
2740
|
-
* @property {Node.Name | Node.Calc | Node.Value} [enum] 列表属性枚举
|
|
2741
2858
|
*
|
|
2742
2859
|
* @property {boolean | string} [bind] 绑定内容
|
|
2743
|
-
* @property {Node.Name | Node.Value | Node.Calc} [text] 文本渲染
|
|
2744
|
-
* @property {Node.Name | Node.Value | Node.Calc} [html] HTML 渲染
|
|
2745
2860
|
*
|
|
2746
2861
|
* @property {string} [comment] 注释
|
|
2747
2862
|
*
|
|
2748
|
-
* @property {
|
|
2863
|
+
* @property {Child[]} children 子元素
|
|
2749
2864
|
*/
|
|
2750
2865
|
|
|
2866
|
+
|
|
2751
2867
|
/**
|
|
2752
2868
|
* @callback Calc 计算函数
|
|
2753
2869
|
* @param {Record<string, any>} env 上下文环境
|
|
@@ -2762,10 +2878,9 @@
|
|
|
2762
2878
|
* @returns {void}
|
|
2763
2879
|
*/
|
|
2764
2880
|
|
|
2765
|
-
var index
|
|
2881
|
+
var index = /*#__PURE__*/Object.freeze({
|
|
2766
2882
|
__proto__: null,
|
|
2767
|
-
parse: parse
|
|
2768
|
-
stringify: stringify
|
|
2883
|
+
parse: parse
|
|
2769
2884
|
});
|
|
2770
2885
|
|
|
2771
2886
|
/**
|
|
@@ -2861,7 +2976,7 @@
|
|
|
2861
2976
|
null: true,
|
|
2862
2977
|
index: true,
|
|
2863
2978
|
no: true,
|
|
2864
|
-
|
|
2979
|
+
size: true,
|
|
2865
2980
|
|
|
2866
2981
|
error: true,
|
|
2867
2982
|
errors: true,
|
|
@@ -2920,7 +3035,7 @@
|
|
|
2920
3035
|
yield [`${key}${sign}downMovable`, {get: () => {
|
|
2921
3036
|
const s = val.index;
|
|
2922
3037
|
if (typeof s !== 'number') { return false; }
|
|
2923
|
-
if (s >= parent.
|
|
3038
|
+
if (s >= parent.size - 1) { return false; }
|
|
2924
3039
|
return true;
|
|
2925
3040
|
}}];
|
|
2926
3041
|
yield [`${key}${sign}remove`, {exec: () => parent.remove(Number(val.index))}];
|
|
@@ -2933,7 +3048,7 @@
|
|
|
2933
3048
|
yield [`${key}${sign}downMove`, {exec: () => {
|
|
2934
3049
|
const s = val.index;
|
|
2935
3050
|
if (typeof s !== 'number') { return; }
|
|
2936
|
-
if (s >= parent.
|
|
3051
|
+
if (s >= parent.size - 1) { return; }
|
|
2937
3052
|
parent.move(s, s + 1);
|
|
2938
3053
|
}}];
|
|
2939
3054
|
}
|
|
@@ -3085,10 +3200,9 @@
|
|
|
3085
3200
|
watch(value, cb) { return watch(() => this.exec(value), cb, true); }
|
|
3086
3201
|
|
|
3087
3202
|
/**
|
|
3088
|
-
* @param {Layout.Node.Name | Layout.Node.Calc | Layout.Node.Value
|
|
3203
|
+
* @param {Layout.Node.Name | Layout.Node.Calc | Layout.Node.Value} en
|
|
3089
3204
|
*/
|
|
3090
3205
|
enum(en) {
|
|
3091
|
-
if (!en) { return true; }
|
|
3092
3206
|
const {name, calc} = en;
|
|
3093
3207
|
if (typeof calc === 'function') { return () => calc(this.getters); }
|
|
3094
3208
|
if (typeof name === 'string') {
|
|
@@ -3274,17 +3388,16 @@
|
|
|
3274
3388
|
const store = this.store;
|
|
3275
3389
|
const parent = this.#parent;
|
|
3276
3390
|
const object = this.#object;
|
|
3391
|
+
for (const [key, item] of toItem(store)) {
|
|
3392
|
+
ais[key] = item;
|
|
3393
|
+
}
|
|
3394
|
+
for (const [key, item] of toParentItem(parent, store)) {
|
|
3395
|
+
ais[key] = item;
|
|
3396
|
+
}
|
|
3277
3397
|
if (object) {
|
|
3278
3398
|
for (const k of Object.keys(object)) {
|
|
3279
3399
|
ais[`$${k}`] = {get: () => object[k]};
|
|
3280
3400
|
}
|
|
3281
|
-
} else {
|
|
3282
|
-
for (const [key, item] of toItem(store)) {
|
|
3283
|
-
ais[key] = item;
|
|
3284
|
-
}
|
|
3285
|
-
for (const [key, item] of toParentItem(parent, store)) {
|
|
3286
|
-
ais[key] = item;
|
|
3287
|
-
}
|
|
3288
3401
|
}
|
|
3289
3402
|
this.#allItems = ais;
|
|
3290
3403
|
return ais;
|
|
@@ -3293,11 +3406,13 @@
|
|
|
3293
3406
|
*
|
|
3294
3407
|
* @param {Store} store
|
|
3295
3408
|
* @param {Store} parent
|
|
3409
|
+
* @param {Record<string, any>} [object]
|
|
3296
3410
|
*/
|
|
3297
|
-
setStore(store, parent) {
|
|
3411
|
+
setStore(store, parent, object) {
|
|
3298
3412
|
const cloned = new Environment(store, this);
|
|
3299
3413
|
if (parent) { cloned.#parent = parent; }
|
|
3300
3414
|
setStore(cloned.#schemaItems, store);
|
|
3415
|
+
if (object) { cloned.#object = object; }
|
|
3301
3416
|
return cloned;
|
|
3302
3417
|
}
|
|
3303
3418
|
/**
|
|
@@ -3314,12 +3429,12 @@
|
|
|
3314
3429
|
}
|
|
3315
3430
|
/**
|
|
3316
3431
|
*
|
|
3317
|
-
* @param {Layout.Node}
|
|
3318
|
-
* @param {Layout.Node}
|
|
3432
|
+
* @param {Record<string, Layout.Node.Name | Layout.Node.Calc | Layout.Node.Value<any>>} params
|
|
3433
|
+
* @param {Record<string, Layout.Node.Name | Layout.Node.Calc | Layout.Node.Value<any>>} attrs
|
|
3319
3434
|
* @param {Environment} sourceEnv
|
|
3320
3435
|
* @param {string | null | boolean} [bind]
|
|
3321
3436
|
*/
|
|
3322
|
-
params(
|
|
3437
|
+
params(params, attrs, sourceEnv, bind) {
|
|
3323
3438
|
/** @type {Store} */
|
|
3324
3439
|
let store = this.store;
|
|
3325
3440
|
if (bind === true) {
|
|
@@ -3398,22 +3513,39 @@
|
|
|
3398
3513
|
}
|
|
3399
3514
|
/**
|
|
3400
3515
|
*
|
|
3401
|
-
* @param {
|
|
3402
|
-
* @
|
|
3516
|
+
* @param {Layout.Variable[]?} [vars]
|
|
3517
|
+
* @returns
|
|
3403
3518
|
*/
|
|
3404
|
-
set(
|
|
3405
|
-
if (
|
|
3519
|
+
set(vars) {
|
|
3520
|
+
if (!vars?.length) { return this; }
|
|
3406
3521
|
const cloned = new Environment(this.store, this);
|
|
3407
3522
|
cloned.#parent = this.#parent;
|
|
3408
3523
|
cloned.#object = this.#object;
|
|
3409
3524
|
const explicit = cloned.#explicit;
|
|
3410
3525
|
const items = cloned.#items;
|
|
3411
|
-
for (const
|
|
3526
|
+
for (const { variable, name, calc, value, init } of vars) {
|
|
3527
|
+
if (init) {
|
|
3528
|
+
const val = new exports.Signal.State(/** @type {any} */(value));
|
|
3529
|
+
if (typeof calc === 'function') {
|
|
3530
|
+
const settable = cloned.settable;
|
|
3531
|
+
cloned.#settable = null;
|
|
3532
|
+
val.set(calc(settable));
|
|
3533
|
+
} else if (name) {
|
|
3534
|
+
const item = items[name];
|
|
3535
|
+
if (!item?.get) { continue; }
|
|
3536
|
+
val.set(item.get());
|
|
3537
|
+
}
|
|
3538
|
+
explicit[variable] = items[variable] = {
|
|
3539
|
+
get: () => { return val.get(); },
|
|
3540
|
+
set: (v) => { val.set(v); },
|
|
3541
|
+
};
|
|
3542
|
+
continue;
|
|
3543
|
+
}
|
|
3412
3544
|
if (typeof calc === 'function') {
|
|
3413
3545
|
const getters = cloned.getters;
|
|
3414
3546
|
cloned.#getters = null;
|
|
3415
3547
|
const val = new exports.Signal.Computed(() => calc(getters));
|
|
3416
|
-
explicit[
|
|
3548
|
+
explicit[variable] = items[variable] = {
|
|
3417
3549
|
get: () => { return val.get(); },
|
|
3418
3550
|
};
|
|
3419
3551
|
continue;
|
|
@@ -3422,34 +3554,17 @@
|
|
|
3422
3554
|
const item = items[name];
|
|
3423
3555
|
if (!item) { continue; }
|
|
3424
3556
|
if (!item.get || !item.store) {
|
|
3425
|
-
explicit[
|
|
3557
|
+
explicit[variable] = items[variable] = item;
|
|
3426
3558
|
continue;
|
|
3427
3559
|
}
|
|
3428
|
-
for (const [k, it] of toItem(item.store,
|
|
3560
|
+
for (const [k, it] of toItem(item.store, variable)) {
|
|
3429
3561
|
explicit[k] = items[k] = it;
|
|
3430
3562
|
}
|
|
3431
3563
|
continue;
|
|
3432
3564
|
}
|
|
3433
|
-
explicit[
|
|
3565
|
+
explicit[variable] = items[variable] = { get: () => { return value; } };
|
|
3434
3566
|
continue;
|
|
3435
3567
|
}
|
|
3436
|
-
for (const [k,{name, calc, value}] of Object.entries(vars)) {
|
|
3437
|
-
|
|
3438
|
-
const val = new exports.Signal.State(/** @type {any} */(value));
|
|
3439
|
-
if (typeof calc === 'function') {
|
|
3440
|
-
const settable = cloned.settable;
|
|
3441
|
-
cloned.#settable = null;
|
|
3442
|
-
val.set(calc(settable));
|
|
3443
|
-
} else if (name) {
|
|
3444
|
-
const item = items[name];
|
|
3445
|
-
if (!item?.get) { continue }
|
|
3446
|
-
val.set(item.get());
|
|
3447
|
-
}
|
|
3448
|
-
explicit[k] = items[k] = {
|
|
3449
|
-
get: () => { return val.get(); },
|
|
3450
|
-
set: (v) => { val.set(v); },
|
|
3451
|
-
};
|
|
3452
|
-
}
|
|
3453
3568
|
return cloned;
|
|
3454
3569
|
}
|
|
3455
3570
|
|
|
@@ -4432,17 +4547,24 @@
|
|
|
4432
4547
|
}
|
|
4433
4548
|
|
|
4434
4549
|
}
|
|
4550
|
+
const count = new exports.Signal.State(0);
|
|
4435
4551
|
const childrenResult = watch(() => store.children, function render(children) {
|
|
4436
4552
|
if (!start.parentNode) { return; }
|
|
4437
4553
|
let nextNode = start.nextSibling;
|
|
4438
4554
|
const oldSeMap = seMap;
|
|
4439
4555
|
seMap = new Map();
|
|
4556
|
+
count.set(children.length);
|
|
4440
4557
|
for (let child of children) {
|
|
4441
4558
|
const old = oldSeMap.get(child);
|
|
4442
4559
|
if (!old) {
|
|
4443
4560
|
const ItemStart = parent.insertBefore(document.createComment(''), nextNode);
|
|
4444
4561
|
const itemEnd = parent.insertBefore(document.createComment(''), nextNode);
|
|
4445
|
-
const d = renderItem(itemEnd, env.setStore(child, store
|
|
4562
|
+
const d = renderItem(itemEnd, env.setStore(child, store, {
|
|
4563
|
+
get count() { return count.get() },
|
|
4564
|
+
get key() { return child.index; },
|
|
4565
|
+
get index() { return child.index; },
|
|
4566
|
+
get item() { return child.value; },
|
|
4567
|
+
}));
|
|
4446
4568
|
seMap.set(child, [ItemStart, itemEnd, d]);
|
|
4447
4569
|
continue;
|
|
4448
4570
|
}
|
|
@@ -4489,18 +4611,18 @@
|
|
|
4489
4611
|
* @param {Element} parent
|
|
4490
4612
|
* @param {Node?} next
|
|
4491
4613
|
* @param {Environment} envs
|
|
4492
|
-
* @param {Layout.Node}
|
|
4614
|
+
* @param {Layout.Node.Name | Layout.Node.Calc | Layout.Node.Value} value
|
|
4615
|
+
* @param {boolean} [isHtml]
|
|
4493
4616
|
*/
|
|
4494
|
-
function renderFillDirectives(parent, next, envs,
|
|
4495
|
-
if (
|
|
4617
|
+
function renderFillDirectives(parent, next, envs, value, isHtml) {
|
|
4618
|
+
if (!isHtml) {
|
|
4496
4619
|
const node = parent.insertBefore(document.createTextNode(''), next);
|
|
4497
|
-
const stop = envs.watch(
|
|
4620
|
+
const stop = envs.watch(value, val => node.textContent = toText(val));
|
|
4498
4621
|
return () => {
|
|
4499
4622
|
node.remove();
|
|
4500
4623
|
stop();
|
|
4501
4624
|
};
|
|
4502
4625
|
}
|
|
4503
|
-
if (html == null) { return; }
|
|
4504
4626
|
const start = parent.insertBefore(document.createComment(''), next);
|
|
4505
4627
|
const end = parent.insertBefore(document.createComment(''), next);
|
|
4506
4628
|
const div = document.createElement('div');
|
|
@@ -4516,7 +4638,7 @@
|
|
|
4516
4638
|
node.remove();
|
|
4517
4639
|
}
|
|
4518
4640
|
}
|
|
4519
|
-
const result = envs.watch(
|
|
4641
|
+
const result = envs.watch(value, val => {
|
|
4520
4642
|
remove();
|
|
4521
4643
|
add(toText(val));
|
|
4522
4644
|
});
|
|
@@ -4528,113 +4650,7 @@
|
|
|
4528
4650
|
};
|
|
4529
4651
|
}
|
|
4530
4652
|
|
|
4531
|
-
/** @import
|
|
4532
|
-
|
|
4533
|
-
/**
|
|
4534
|
-
* @param {(Layout.Node | string)[]} layouts
|
|
4535
|
-
* @param {Element} parent
|
|
4536
|
-
* @param {Node?} next
|
|
4537
|
-
* @param {Environment} envs
|
|
4538
|
-
* @param {Record<string, [Layout.Node, Environment]>} templates
|
|
4539
|
-
* @param {(layout: Layout.Node, templates: Record<string, any>) => () => void} renderItem
|
|
4540
|
-
* @returns {() => void}
|
|
4541
|
-
*/
|
|
4542
|
-
function renderList(layouts, parent, next, envs, templates, renderItem) {
|
|
4543
|
-
|
|
4544
|
-
/** @type {Set<() => void>?} */
|
|
4545
|
-
let bkList = new Set();
|
|
4546
|
-
/** @type {[Layout.Node.Name | Layout.Node.Calc | Layout.Node.Value | null, Layout.Node][]} */
|
|
4547
|
-
let ifList = [];
|
|
4548
|
-
/** @type {Record<string, [Layout.Node, Environment]>} */
|
|
4549
|
-
let currentTemplates = Object.create(templates);
|
|
4550
|
-
for (const layout of layouts) {
|
|
4551
|
-
if (typeof layout === 'string') { continue; }
|
|
4552
|
-
const name = layout.template;
|
|
4553
|
-
if (!name) { continue; }
|
|
4554
|
-
currentTemplates[name] = [layout, envs];
|
|
4555
|
-
}
|
|
4556
|
-
|
|
4557
|
-
/** @param {[Layout.Node.Name | Layout.Node.Calc | Layout.Node.Value | null, Layout.Node][]} list */
|
|
4558
|
-
function renderIf(list) {
|
|
4559
|
-
if (!list.length || !bkList) { return; }
|
|
4560
|
-
const end = parent.insertBefore(document.createComment(''), next);
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
let lastIndex = -1;
|
|
4564
|
-
let destroy = () => { };
|
|
4565
|
-
/**
|
|
4566
|
-
*
|
|
4567
|
-
* @param {number} index
|
|
4568
|
-
* @returns
|
|
4569
|
-
*/
|
|
4570
|
-
function renderIndex(index) {
|
|
4571
|
-
const layout = list[index]?.[1];
|
|
4572
|
-
if (!layout) { return; }
|
|
4573
|
-
destroy = renderItem(layout, currentTemplates);
|
|
4574
|
-
}
|
|
4575
|
-
bkList.add(() => {
|
|
4576
|
-
destroy();
|
|
4577
|
-
destroy = () => { };
|
|
4578
|
-
end.remove();
|
|
4579
|
-
});
|
|
4580
|
-
bkList.add(watch(
|
|
4581
|
-
() => list.findIndex(([ifv]) => !ifv || envs.exec(ifv)),
|
|
4582
|
-
index => {
|
|
4583
|
-
if (index === lastIndex) { return; }
|
|
4584
|
-
lastIndex = index;
|
|
4585
|
-
destroy();
|
|
4586
|
-
destroy = () => { };
|
|
4587
|
-
renderIndex(lastIndex);
|
|
4588
|
-
}, true,
|
|
4589
|
-
));
|
|
4590
|
-
}
|
|
4591
|
-
for (const layout of layouts) {
|
|
4592
|
-
if (typeof layout === 'string') {
|
|
4593
|
-
renderIf(ifList);
|
|
4594
|
-
ifList = [];
|
|
4595
|
-
const node = document.createTextNode(layout);
|
|
4596
|
-
parent.insertBefore(node, next);
|
|
4597
|
-
bkList.add(() => node.remove());
|
|
4598
|
-
continue;
|
|
4599
|
-
}
|
|
4600
|
-
if (layout.template) {
|
|
4601
|
-
renderIf(ifList);
|
|
4602
|
-
ifList = [];
|
|
4603
|
-
continue;
|
|
4604
|
-
}
|
|
4605
|
-
if (ifList.length && layout.else) {
|
|
4606
|
-
const ifv = layout.if || null;
|
|
4607
|
-
ifList.push([ifv, layout]);
|
|
4608
|
-
if (!ifv) {
|
|
4609
|
-
renderIf(ifList);
|
|
4610
|
-
ifList = [];
|
|
4611
|
-
}
|
|
4612
|
-
continue;
|
|
4613
|
-
}
|
|
4614
|
-
renderIf(ifList);
|
|
4615
|
-
ifList = [];
|
|
4616
|
-
const ifv = layout.if;
|
|
4617
|
-
if (ifv) {
|
|
4618
|
-
ifList.push([ifv, layout]);
|
|
4619
|
-
continue;
|
|
4620
|
-
}
|
|
4621
|
-
bkList.add(
|
|
4622
|
-
renderItem(layout, currentTemplates)
|
|
4623
|
-
);
|
|
4624
|
-
}
|
|
4625
|
-
renderIf(ifList);
|
|
4626
|
-
|
|
4627
|
-
return () => {
|
|
4628
|
-
if (!bkList) { return; }
|
|
4629
|
-
const list = bkList;
|
|
4630
|
-
bkList = null;
|
|
4631
|
-
for (const s of list) {
|
|
4632
|
-
s();
|
|
4633
|
-
}
|
|
4634
|
-
};
|
|
4635
|
-
}
|
|
4636
|
-
|
|
4637
|
-
/** @import { ObjectStore } from '../Store/index.mjs' */
|
|
4653
|
+
/** @import { ObjectStore, Store } from '../Store/index.mjs' */
|
|
4638
4654
|
|
|
4639
4655
|
/**
|
|
4640
4656
|
*
|
|
@@ -4647,8 +4663,16 @@
|
|
|
4647
4663
|
function renderObject(parent, next, store, env, renderItem) {
|
|
4648
4664
|
/** @type {(() => void)[]} */
|
|
4649
4665
|
const children = [];
|
|
4650
|
-
|
|
4651
|
-
|
|
4666
|
+
/** @type {[string, Store<any, any>, number][]} */
|
|
4667
|
+
const childStores = [...store].map(([k,v], i) => [k,v,i]);
|
|
4668
|
+
const count = childStores.length;
|
|
4669
|
+
for (const [key, child, index] of childStores) {
|
|
4670
|
+
children.push(renderItem(next, env.setStore(child, store, {
|
|
4671
|
+
get count() { return count; },
|
|
4672
|
+
get key() { return key; },
|
|
4673
|
+
get index() { return index; },
|
|
4674
|
+
get item() { return child.value; },
|
|
4675
|
+
})));
|
|
4652
4676
|
}
|
|
4653
4677
|
|
|
4654
4678
|
return () => {
|
|
@@ -4694,11 +4718,13 @@
|
|
|
4694
4718
|
e.remove();
|
|
4695
4719
|
}
|
|
4696
4720
|
}
|
|
4721
|
+
const count = new exports.Signal.State(0);
|
|
4697
4722
|
const childrenResult = watch(() => list.get(), function render(children) {
|
|
4698
4723
|
if (!start.parentNode) { return; }
|
|
4699
4724
|
let nextNode = start.nextSibling;
|
|
4700
4725
|
const oldSeMap = seMap;
|
|
4701
4726
|
seMap = [];
|
|
4727
|
+
count.set(children.length);
|
|
4702
4728
|
for (const [value, index, key] of children) {
|
|
4703
4729
|
const index2 = oldSeMap.findIndex((v) => v[3] === key);
|
|
4704
4730
|
const [old] = index2 >= 0 ? oldSeMap.splice(index2, 1) : [];
|
|
@@ -4708,8 +4734,9 @@
|
|
|
4708
4734
|
const valueState = new exports.Signal.State(value);
|
|
4709
4735
|
const indexState = new exports.Signal.State(index);
|
|
4710
4736
|
const d = renderItem(itemEnd, env.setObject({
|
|
4737
|
+
get count() { return count.get() },
|
|
4711
4738
|
get key() { return key; },
|
|
4712
|
-
get
|
|
4739
|
+
get item() { return valueState.get(); },
|
|
4713
4740
|
get index() { return indexState.get(); },
|
|
4714
4741
|
}));
|
|
4715
4742
|
seMap.push([ItemStart, itemEnd, d, key, valueState, indexState]);
|
|
@@ -4898,6 +4925,50 @@
|
|
|
4898
4925
|
};
|
|
4899
4926
|
}
|
|
4900
4927
|
|
|
4928
|
+
/** @import * as Layout from '../Layout/index.mjs' */
|
|
4929
|
+
|
|
4930
|
+
/**
|
|
4931
|
+
* @param {Layout.Divergent} layout
|
|
4932
|
+
* @param {Element} parent
|
|
4933
|
+
* @param {Node?} next
|
|
4934
|
+
* @param {Environment} env
|
|
4935
|
+
* @param {(layout: Layout.Child[], vars?: Layout.Variable[]?, templates?: Record<string, any>) => () => void} renderItem
|
|
4936
|
+
* @returns {() => void}
|
|
4937
|
+
*/
|
|
4938
|
+
function divergent(layout, parent, next, env, renderItem) {
|
|
4939
|
+
const children = layout.children;
|
|
4940
|
+
if (!children.length) { return () => { }; }
|
|
4941
|
+
const end = parent.insertBefore(document.createComment(''), next);
|
|
4942
|
+
/** @type {typeof children[0]?} */
|
|
4943
|
+
let last = null;
|
|
4944
|
+
let destroy = () => { };
|
|
4945
|
+
const stop = () => {
|
|
4946
|
+
destroy();
|
|
4947
|
+
destroy = () => { };
|
|
4948
|
+
end.remove();
|
|
4949
|
+
};
|
|
4950
|
+
const unwatch = watch(
|
|
4951
|
+
() => children.find(([, ifv]) => !ifv || env.exec(ifv)) || null,
|
|
4952
|
+
item => {
|
|
4953
|
+
if (item === last) { return; }
|
|
4954
|
+
last = item;
|
|
4955
|
+
destroy();
|
|
4956
|
+
destroy = () => { };
|
|
4957
|
+
const layout = item?.[0];
|
|
4958
|
+
if (!layout) { return; }
|
|
4959
|
+
destroy = renderItem(layout.children, layout.vars, layout.templates);
|
|
4960
|
+
}, true,
|
|
4961
|
+
);
|
|
4962
|
+
|
|
4963
|
+
let destroyed = false;
|
|
4964
|
+
return () => {
|
|
4965
|
+
if (destroyed) { return; }
|
|
4966
|
+
destroyed = true;
|
|
4967
|
+
unwatch();
|
|
4968
|
+
stop();
|
|
4969
|
+
};
|
|
4970
|
+
}
|
|
4971
|
+
|
|
4901
4972
|
/** @import Store from '../Store/index.mjs' */
|
|
4902
4973
|
|
|
4903
4974
|
/**
|
|
@@ -4905,37 +4976,19 @@
|
|
|
4905
4976
|
* @param {Element} parent
|
|
4906
4977
|
* @param {Node?} next
|
|
4907
4978
|
* @param {Environment} env
|
|
4908
|
-
* @param {Record<string, [Layout.
|
|
4979
|
+
* @param {Record<string, [Layout.Template, Environment]>} templates
|
|
4909
4980
|
* @param {string[]} componentPath
|
|
4910
4981
|
* @param {Record<string, Enhancement>} enhancements
|
|
4911
4982
|
* @param {((store: Store, el: Element | Relatedness) => () => void)?} [relate]
|
|
4912
4983
|
* @param {Component.Getter?} [getComponent]
|
|
4913
4984
|
*/
|
|
4914
|
-
function
|
|
4915
|
-
env = env.set(layout.aliases, layout.vars);
|
|
4985
|
+
function renderNode(layout, parent, next, env, templates, componentPath, enhancements, relate, getComponent) {
|
|
4916
4986
|
const bind = layout.bind;
|
|
4917
|
-
const fragment = layout.fragment;
|
|
4918
|
-
if (fragment && typeof fragment === 'string') {
|
|
4919
|
-
const template = templates[fragment];
|
|
4920
|
-
if (!template) { return () => {}; }
|
|
4921
|
-
const [templateLayout, templateEnv] = template;
|
|
4922
|
-
const newEnv = templateEnv.params(templateLayout, layout, env, bind);
|
|
4923
|
-
return render(templateLayout, parent, next, newEnv, templates, componentPath, enhancements, relate, getComponent);
|
|
4924
|
-
}
|
|
4925
|
-
if (!layout.name || layout.fragment) {
|
|
4926
|
-
return renderFillDirectives(parent, next, env, layout) ||
|
|
4927
|
-
renderList(layout.children || [], parent, next, env, templates, (layout, templates) => {
|
|
4928
|
-
return render(layout, parent, next, env, templates, componentPath, enhancements, relate, getComponent);
|
|
4929
|
-
});
|
|
4930
|
-
}
|
|
4931
4987
|
const path = [...componentPath, layout.name];
|
|
4932
4988
|
const component = getComponent?.(path);
|
|
4933
4989
|
if (getComponent && !component) { return () => { }; }
|
|
4934
4990
|
const { context, handler } = createContext(
|
|
4935
|
-
component ? component : layout.name,
|
|
4936
|
-
env,
|
|
4937
|
-
env.getStore(bind),
|
|
4938
|
-
relate
|
|
4991
|
+
component ? component : layout.name, env, env.getStore(bind), relate
|
|
4939
4992
|
);
|
|
4940
4993
|
|
|
4941
4994
|
const componentAttrs = component?.attrs;
|
|
@@ -4959,11 +5012,9 @@
|
|
|
4959
5012
|
const root = Array.isArray(r) ? r[0] : r;
|
|
4960
5013
|
const slot = Array.isArray(r) ? r[1] : root;
|
|
4961
5014
|
parent.insertBefore(root, next);
|
|
4962
|
-
const children = slot ?
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
return render(layout, slot, null, env, templates, componentPath, enhancements, relate, getComponent);
|
|
4966
|
-
}) : () => {};
|
|
5015
|
+
const children = slot ?
|
|
5016
|
+
renderChildren(layout.children || [], slot, null, env, templates, componentPath, enhancements, relate, getComponent)
|
|
5017
|
+
: () => { };
|
|
4967
5018
|
|
|
4968
5019
|
|
|
4969
5020
|
const classes = bindClasses(root, env, layout.classes, layout.attrs.class);
|
|
@@ -4971,7 +5022,7 @@
|
|
|
4971
5022
|
|
|
4972
5023
|
handler.mount();
|
|
4973
5024
|
const enhancement = bindEnhancements(handler.tag, layout.enhancements, env, enhancements, root, slot);
|
|
4974
|
-
|
|
5025
|
+
|
|
4975
5026
|
return () => {
|
|
4976
5027
|
enhancement();
|
|
4977
5028
|
handler.destroy();
|
|
@@ -4983,43 +5034,117 @@
|
|
|
4983
5034
|
styles();
|
|
4984
5035
|
};
|
|
4985
5036
|
}
|
|
5037
|
+
|
|
4986
5038
|
/**
|
|
4987
5039
|
*
|
|
4988
|
-
* @param {
|
|
5040
|
+
* @param {Environment} env
|
|
5041
|
+
* @param {Record<string, [Layout.Template, Environment]>} parentTemplates
|
|
5042
|
+
* @param {Record<string, Layout.Template>} [newTemplates]
|
|
5043
|
+
* @returns {Record<string, [Layout.Template, Environment]>}
|
|
5044
|
+
*/
|
|
5045
|
+
function createTemplates(env, parentTemplates, newTemplates) {
|
|
5046
|
+
if (!newTemplates) { return parentTemplates; } const layOutTemplates = Object.entries(newTemplates);
|
|
5047
|
+
if (!layOutTemplates.length) { return parentTemplates; }
|
|
5048
|
+
/** @type {Record<string, [Layout.Template, Environment]>} */
|
|
5049
|
+
const templates = Object.create(parentTemplates);
|
|
5050
|
+
for (const [name, template] of layOutTemplates) {
|
|
5051
|
+
templates[name] = [template, env];
|
|
5052
|
+
}
|
|
5053
|
+
return templates;
|
|
5054
|
+
}
|
|
5055
|
+
/**
|
|
5056
|
+
*
|
|
5057
|
+
* @param {Layout.Child} layout
|
|
4989
5058
|
* @param {Element} parent
|
|
4990
5059
|
* @param {Node?} next
|
|
4991
|
-
* @param {Environment}
|
|
4992
|
-
* @param {Record<string, [Layout.
|
|
5060
|
+
* @param {Environment} parentEnv
|
|
5061
|
+
* @param {Record<string, [Layout.Template, Environment]>} parentTemplates
|
|
4993
5062
|
* @param {string[]} componentPath
|
|
4994
5063
|
* @param {Record<string, Enhancement>} enhancements
|
|
4995
5064
|
* @param {((store: Store, el: Element | Relatedness) => () => void)?} [relate]
|
|
4996
5065
|
* @param {Component.Getter?} [getComponent]
|
|
4997
5066
|
* @returns {() => void}
|
|
4998
5067
|
*/
|
|
4999
|
-
function
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
const r = (next, env) => renderItem(layout, parent, next, env, templates, componentPath, enhancements, relate, getComponent);
|
|
5005
|
-
if (list === true) {
|
|
5006
|
-
return r(next, newEnv);
|
|
5068
|
+
function renderChild(layout, parent, next, parentEnv, parentTemplates, componentPath, enhancements, relate, getComponent) {
|
|
5069
|
+
if (typeof layout === 'string') {
|
|
5070
|
+
const node = document.createTextNode(layout);
|
|
5071
|
+
parent.insertBefore(node, next);
|
|
5072
|
+
return () => node.remove();
|
|
5007
5073
|
}
|
|
5008
|
-
|
|
5009
|
-
|
|
5074
|
+
const env = parentEnv.set(layout.vars);
|
|
5075
|
+
const templates = createTemplates(env, parentTemplates, layout.templates);
|
|
5076
|
+
if (layout.type === 'divergent') {
|
|
5077
|
+
return divergent(layout, parent, next, env, (list, vars, templates2) => {
|
|
5078
|
+
const listEnv = env.set(vars);
|
|
5079
|
+
const templates = createTemplates(listEnv, parentTemplates, templates2);
|
|
5080
|
+
return renderChildren(list, parent, next, listEnv, templates, componentPath, enhancements, relate, getComponent);
|
|
5081
|
+
});
|
|
5010
5082
|
}
|
|
5011
|
-
if (
|
|
5012
|
-
|
|
5083
|
+
if (layout.type === 'value') {
|
|
5084
|
+
const newEnv = env.child(layout.name);
|
|
5085
|
+
if (!newEnv) { return () => { }; }
|
|
5086
|
+
return renderChildren(layout.children, parent, next, newEnv, templates, componentPath, enhancements, relate, getComponent);
|
|
5013
5087
|
}
|
|
5014
|
-
if (
|
|
5015
|
-
|
|
5088
|
+
if (layout.type === 'enum') {
|
|
5089
|
+
const list = env.enum(layout.value);
|
|
5090
|
+
/** @type {(next: Node | null, env: any) => () => void} */
|
|
5091
|
+
const r = (next, env) => renderChildren(layout.children, parent, next, env, templates, componentPath, enhancements, relate, getComponent);
|
|
5092
|
+
if (list instanceof ArrayStore) {
|
|
5093
|
+
return renderArray(parent, next, list, env, r);
|
|
5094
|
+
}
|
|
5095
|
+
if (list instanceof ObjectStore) {
|
|
5096
|
+
return renderObject(parent, next, list, env, r);
|
|
5097
|
+
}
|
|
5098
|
+
if (typeof list === 'function') {
|
|
5099
|
+
return renderEnum(parent, next, list, env, r);
|
|
5100
|
+
}
|
|
5101
|
+
return () => { };
|
|
5016
5102
|
}
|
|
5017
|
-
|
|
5103
|
+
if (layout.type === 'content') {
|
|
5104
|
+
return renderFillDirectives(parent, next, env, layout.value, layout.html);
|
|
5105
|
+
}
|
|
5106
|
+
if (layout.type === 'template') {
|
|
5107
|
+
const template = templates[layout.template];
|
|
5108
|
+
if (!template) { return () => { }; }
|
|
5109
|
+
const [templateLayout, templateEnv] = template;
|
|
5110
|
+
const newEnv = templateEnv.params(templateLayout.params, layout.attrs, env, layout.bind);
|
|
5111
|
+
const subTemplates = createTemplates(newEnv, parentTemplates, templateLayout.templates);
|
|
5112
|
+
return renderChildren(templateLayout.children, parent, next, newEnv, subTemplates, componentPath, enhancements, relate, getComponent);
|
|
5113
|
+
}
|
|
5114
|
+
if (layout.type === 'fragment') {
|
|
5115
|
+
return renderChildren(layout.children, parent, next, env, templates, componentPath, enhancements, relate, getComponent);
|
|
5116
|
+
}
|
|
5117
|
+
return renderNode(layout, parent, next, env, templates, componentPath, enhancements, relate, getComponent);
|
|
5118
|
+
}
|
|
5119
|
+
|
|
5120
|
+
/**
|
|
5121
|
+
*
|
|
5122
|
+
* @param {Layout.Child[]} layouts
|
|
5123
|
+
* @param {Element} parent
|
|
5124
|
+
* @param {Node?} next
|
|
5125
|
+
* @param {Environment} env
|
|
5126
|
+
* @param {Record<string, [Layout.Template, Environment]>} templates
|
|
5127
|
+
* @param {string[]} componentPath
|
|
5128
|
+
* @param {Record<string, Enhancement>} enhancements
|
|
5129
|
+
* @param {((store: Store, el: Element | Relatedness) => () => void)?} [relate]
|
|
5130
|
+
* @param {Component.Getter?} [getComponent]
|
|
5131
|
+
* @returns {() => void}
|
|
5132
|
+
*/
|
|
5133
|
+
function renderChildren(layouts, parent, next, env, templates, componentPath, enhancements, relate, getComponent) {
|
|
5134
|
+
const list = layouts.map(v => renderChild(v, parent, next, env, templates, componentPath, enhancements, relate, getComponent));
|
|
5135
|
+
let removed = false;
|
|
5136
|
+
return () => {
|
|
5137
|
+
if (removed) { return; }
|
|
5138
|
+
removed = true;
|
|
5139
|
+
for (const k of list) {
|
|
5140
|
+
k();
|
|
5141
|
+
}
|
|
5142
|
+
};
|
|
5018
5143
|
}
|
|
5019
5144
|
|
|
5020
5145
|
/**
|
|
5021
5146
|
* @param {Store} store 存储实例
|
|
5022
|
-
* @param {
|
|
5147
|
+
* @param {Layout.Child[]} layouts 布局信息
|
|
5023
5148
|
* @param {Element} parent 渲染节点
|
|
5024
5149
|
* @param {object} [options] 选项
|
|
5025
5150
|
* @param {Record<string, Store | {get?(): any; set?(v: any): void; exec?(...p: any[]): any; calc?(...p: any[]): any }>} [options.global] 全局数据
|
|
@@ -5028,20 +5153,18 @@
|
|
|
5028
5153
|
* @param {Record<string, Enhancement>} [options.enhancements] 增强信息
|
|
5029
5154
|
* @returns {() => void}
|
|
5030
5155
|
*/
|
|
5031
|
-
function
|
|
5156
|
+
function render(store, layouts, parent, { component, global, relate, enhancements } = {}) {
|
|
5032
5157
|
const env = new Environment(store, global);
|
|
5033
5158
|
const templates = Object.create(null);
|
|
5034
5159
|
const allEnhancements = enhancements || {};
|
|
5035
|
-
const relateFn = typeof relate
|
|
5036
|
-
return
|
|
5037
|
-
return render(layout, parent, null, env, templates, [], allEnhancements, relateFn, component);
|
|
5038
|
-
});
|
|
5160
|
+
const relateFn = typeof relate === 'function' ? relate : null;
|
|
5161
|
+
return renderChildren(layouts, parent, null, env, templates, [], allEnhancements, relateFn, component);
|
|
5039
5162
|
}
|
|
5040
5163
|
|
|
5041
|
-
exports.Layout = index
|
|
5164
|
+
exports.Layout = index;
|
|
5042
5165
|
exports.Store = Store;
|
|
5043
5166
|
exports.effect = effect;
|
|
5044
|
-
exports.render =
|
|
5167
|
+
exports.render = render;
|
|
5045
5168
|
exports.watch = watch;
|
|
5046
5169
|
|
|
5047
5170
|
}));
|