@thomas-siegfried/tapout 0.0.1 → 0.0.3

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.
Files changed (52) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +1207 -1205
  3. package/decorator-config.md +220 -0
  4. package/dist/wireParams.d.ts.map +1 -1
  5. package/dist/wireParams.js +27 -4
  6. package/dist/wireParams.js.map +1 -1
  7. package/llms.txt +360 -0
  8. package/package.json +57 -55
  9. package/src/applyBindings.ts +372 -372
  10. package/src/arrayToDomMapping.ts +300 -300
  11. package/src/attributeInterpolationMarkup.ts +91 -91
  12. package/src/bindingContext.ts +207 -207
  13. package/src/bindingEvent.ts +198 -198
  14. package/src/bindingProvider.ts +260 -260
  15. package/src/bindings.ts +963 -963
  16. package/src/compareArrays.ts +122 -122
  17. package/src/componentBinding.ts +318 -318
  18. package/src/componentDecorator.ts +62 -62
  19. package/src/components.ts +367 -367
  20. package/src/computed.ts +439 -439
  21. package/src/configure.ts +52 -52
  22. package/src/controlFlowBindings.ts +206 -206
  23. package/src/core.ts +60 -60
  24. package/src/decorators.ts +407 -407
  25. package/src/dependencyDetection.ts +76 -76
  26. package/src/disposable.ts +36 -36
  27. package/src/domData.ts +42 -42
  28. package/src/domNodeDisposal.ts +94 -94
  29. package/src/effects.ts +29 -29
  30. package/src/event.ts +173 -173
  31. package/src/expressionRewriting.ts +219 -219
  32. package/src/extenders.ts +102 -102
  33. package/src/filters.ts +91 -91
  34. package/src/index.ts +150 -150
  35. package/src/interpolationMarkup.ts +130 -130
  36. package/src/memoization.ts +71 -71
  37. package/src/namespacedBindings.ts +132 -132
  38. package/src/observable.ts +48 -48
  39. package/src/observableArray.ts +397 -397
  40. package/src/options.ts +25 -25
  41. package/src/selectExtensions.ts +68 -68
  42. package/src/slotBinding.ts +84 -84
  43. package/src/subscribable.ts +266 -266
  44. package/src/tasks.ts +79 -79
  45. package/src/templateEngine.ts +108 -108
  46. package/src/templateRendering.ts +399 -399
  47. package/src/templateRewriting.ts +94 -94
  48. package/src/templateSources.ts +134 -134
  49. package/src/utils.ts +123 -123
  50. package/src/utilsDom.ts +87 -87
  51. package/src/virtualElements.ts +153 -153
  52. package/src/wireParams.ts +69 -49
@@ -1,94 +1,94 @@
1
- import { parseObjectLiteral, preProcessBindings } from './expressionRewriting.js';
2
- import type { KeyValuePair } from './expressionRewriting.js';
3
- import { memoize } from './memoization.js';
4
- import type { TemplateEngine } from './templateEngine.js';
5
- import type { BindingContext } from './bindingContext.js';
6
- import { applyBindingAccessorsToNode } from './applyBindings.js';
7
-
8
- const memoizeDataBindingAttributeSyntaxRegex =
9
- /(<([a-z]+\d*)(?:\s+(?!data-bind\s*=\s*)[a-z0-9\-]+(?:=(?:"[^"]*"|'[^']*'|[^>]*))?)*\s+)data-bind\s*=\s*(["'])([\s\S]*?)\3/gi;
10
-
11
- const memoizeVirtualContainerBindingSyntaxRegex =
12
- /<!--\s*tap\b\s*([\s\S]*?)\s*-->/g;
13
-
14
- export const bindingRewriteValidators: Record<string, boolean | ((value: string) => string | void)> = {};
15
-
16
- function validateDataBindValuesForRewriting(keyValueArray: KeyValuePair[]): void {
17
- for (const kv of keyValueArray) {
18
- const key = kv.key;
19
- if (key && Object.prototype.hasOwnProperty.call(bindingRewriteValidators, key)) {
20
- const validator = bindingRewriteValidators[key];
21
- if (typeof validator === 'function') {
22
- const msg = validator(kv.value || '');
23
- if (msg) throw new Error(msg);
24
- } else if (!validator) {
25
- throw new Error("This template engine does not support the '" + key + "' binding within its templates");
26
- }
27
- }
28
- }
29
- }
30
-
31
- function constructMemoizedTagReplacement(
32
- dataBindAttributeValue: string,
33
- tagToRetain: string,
34
- nodeName: string,
35
- templateEngine: TemplateEngine,
36
- ): string {
37
- const dataBindKeyValueArray = parseObjectLiteral(dataBindAttributeValue);
38
- validateDataBindValuesForRewriting(dataBindKeyValueArray);
39
- const rewrittenDataBindAttributeValue = preProcessBindings(dataBindKeyValueArray, { valueAccessors: true });
40
-
41
- const applyBindingsToNextSiblingScript =
42
- "tap.__tr_ambtns(function($context,$element){return(function(){return{ " +
43
- rewrittenDataBindAttributeValue +
44
- " } })()},'" + nodeName.toLowerCase() + "')";
45
- return templateEngine.createJavaScriptEvaluatorBlock(applyBindingsToNextSiblingScript) + tagToRetain;
46
- }
47
-
48
- export function ensureTemplateIsRewritten(
49
- template: string | Node,
50
- templateEngine: TemplateEngine,
51
- templateDocument?: Document,
52
- ): void {
53
- if (!templateEngine.isTemplateRewritten(template, templateDocument)) {
54
- templateEngine.rewriteTemplate(template, (htmlString) => {
55
- return memoizeBindingAttributeSyntax(htmlString, templateEngine);
56
- }, templateDocument);
57
- }
58
- }
59
-
60
- export function memoizeBindingAttributeSyntax(
61
- htmlString: string,
62
- templateEngine: TemplateEngine,
63
- ): string {
64
- return htmlString
65
- .replace(memoizeDataBindingAttributeSyntaxRegex, function () {
66
- return constructMemoizedTagReplacement(
67
- arguments[4], // dataBindAttributeValue
68
- arguments[1], // tagToRetain
69
- arguments[2], // nodeName
70
- templateEngine,
71
- );
72
- })
73
- .replace(memoizeVirtualContainerBindingSyntaxRegex, function () {
74
- return constructMemoizedTagReplacement(
75
- arguments[1], // dataBindAttributeValue
76
- '<!-- tap -->', // tagToRetain
77
- '#comment', // nodeName
78
- templateEngine,
79
- );
80
- });
81
- }
82
-
83
- export function applyMemoizedBindingsToNextSibling(
84
- bindings: ((ctx: BindingContext, el: Node) => Record<string, () => unknown>),
85
- nodeName: string,
86
- ): string {
87
- return memoize(function (domNode: unknown, bindingContext: unknown) {
88
- const node = domNode as Node;
89
- const nodeToBind = node.nextSibling;
90
- if (nodeToBind && nodeToBind.nodeName.toLowerCase() === nodeName) {
91
- applyBindingAccessorsToNode(nodeToBind, bindings, bindingContext);
92
- }
93
- });
94
- }
1
+ import { parseObjectLiteral, preProcessBindings } from './expressionRewriting.js';
2
+ import type { KeyValuePair } from './expressionRewriting.js';
3
+ import { memoize } from './memoization.js';
4
+ import type { TemplateEngine } from './templateEngine.js';
5
+ import type { BindingContext } from './bindingContext.js';
6
+ import { applyBindingAccessorsToNode } from './applyBindings.js';
7
+
8
+ const memoizeDataBindingAttributeSyntaxRegex =
9
+ /(<([a-z]+\d*)(?:\s+(?!data-bind\s*=\s*)[a-z0-9\-]+(?:=(?:"[^"]*"|'[^']*'|[^>]*))?)*\s+)data-bind\s*=\s*(["'])([\s\S]*?)\3/gi;
10
+
11
+ const memoizeVirtualContainerBindingSyntaxRegex =
12
+ /<!--\s*tap\b\s*([\s\S]*?)\s*-->/g;
13
+
14
+ export const bindingRewriteValidators: Record<string, boolean | ((value: string) => string | void)> = {};
15
+
16
+ function validateDataBindValuesForRewriting(keyValueArray: KeyValuePair[]): void {
17
+ for (const kv of keyValueArray) {
18
+ const key = kv.key;
19
+ if (key && Object.prototype.hasOwnProperty.call(bindingRewriteValidators, key)) {
20
+ const validator = bindingRewriteValidators[key];
21
+ if (typeof validator === 'function') {
22
+ const msg = validator(kv.value || '');
23
+ if (msg) throw new Error(msg);
24
+ } else if (!validator) {
25
+ throw new Error("This template engine does not support the '" + key + "' binding within its templates");
26
+ }
27
+ }
28
+ }
29
+ }
30
+
31
+ function constructMemoizedTagReplacement(
32
+ dataBindAttributeValue: string,
33
+ tagToRetain: string,
34
+ nodeName: string,
35
+ templateEngine: TemplateEngine,
36
+ ): string {
37
+ const dataBindKeyValueArray = parseObjectLiteral(dataBindAttributeValue);
38
+ validateDataBindValuesForRewriting(dataBindKeyValueArray);
39
+ const rewrittenDataBindAttributeValue = preProcessBindings(dataBindKeyValueArray, { valueAccessors: true });
40
+
41
+ const applyBindingsToNextSiblingScript =
42
+ "tap.__tr_ambtns(function($context,$element){return(function(){return{ " +
43
+ rewrittenDataBindAttributeValue +
44
+ " } })()},'" + nodeName.toLowerCase() + "')";
45
+ return templateEngine.createJavaScriptEvaluatorBlock(applyBindingsToNextSiblingScript) + tagToRetain;
46
+ }
47
+
48
+ export function ensureTemplateIsRewritten(
49
+ template: string | Node,
50
+ templateEngine: TemplateEngine,
51
+ templateDocument?: Document,
52
+ ): void {
53
+ if (!templateEngine.isTemplateRewritten(template, templateDocument)) {
54
+ templateEngine.rewriteTemplate(template, (htmlString) => {
55
+ return memoizeBindingAttributeSyntax(htmlString, templateEngine);
56
+ }, templateDocument);
57
+ }
58
+ }
59
+
60
+ export function memoizeBindingAttributeSyntax(
61
+ htmlString: string,
62
+ templateEngine: TemplateEngine,
63
+ ): string {
64
+ return htmlString
65
+ .replace(memoizeDataBindingAttributeSyntaxRegex, function () {
66
+ return constructMemoizedTagReplacement(
67
+ arguments[4], // dataBindAttributeValue
68
+ arguments[1], // tagToRetain
69
+ arguments[2], // nodeName
70
+ templateEngine,
71
+ );
72
+ })
73
+ .replace(memoizeVirtualContainerBindingSyntaxRegex, function () {
74
+ return constructMemoizedTagReplacement(
75
+ arguments[1], // dataBindAttributeValue
76
+ '<!-- tap -->', // tagToRetain
77
+ '#comment', // nodeName
78
+ templateEngine,
79
+ );
80
+ });
81
+ }
82
+
83
+ export function applyMemoizedBindingsToNextSibling(
84
+ bindings: ((ctx: BindingContext, el: Node) => Record<string, () => unknown>),
85
+ nodeName: string,
86
+ ): string {
87
+ return memoize(function (domNode: unknown, bindingContext: unknown) {
88
+ const node = domNode as Node;
89
+ const nodeToBind = node.nextSibling;
90
+ if (nodeToBind && nodeToBind.nodeName.toLowerCase() === nodeName) {
91
+ applyBindingAccessorsToNode(nodeToBind, bindings, bindingContext);
92
+ }
93
+ });
94
+ }
@@ -1,134 +1,134 @@
1
- import { domDataGet, domDataSet, domDataNextKey } from './domData.js';
2
- import { parseHtmlFragment } from './utilsDom.js';
3
-
4
- const enum TemplateType {
5
- Script = 1,
6
- TextArea = 2,
7
- Template = 3,
8
- Element = 4,
9
- }
10
-
11
- const dataDomDataPrefix = domDataNextKey();
12
- const templatesDomDataKey = domDataNextKey();
13
-
14
- interface TemplateDomData {
15
- containerData?: DocumentFragment | HTMLElement;
16
- alwaysCheckText?: boolean;
17
- textData?: string;
18
- }
19
-
20
- function getTemplateDomData(element: Node): TemplateDomData {
21
- return (domDataGet(element, templatesDomDataKey) as TemplateDomData) || {};
22
- }
23
-
24
- function setTemplateDomData(element: Node, data: TemplateDomData): void {
25
- domDataSet(element, templatesDomDataKey, data);
26
- }
27
-
28
- export class DomElementSource {
29
- readonly domElement: Element;
30
- private templateType: TemplateType;
31
-
32
- constructor(element: Element) {
33
- this.domElement = element;
34
- const tagName = element.tagName?.toLowerCase();
35
- this.templateType =
36
- tagName === 'script' ? TemplateType.Script :
37
- tagName === 'textarea' ? TemplateType.TextArea :
38
- tagName === 'template' && (element as HTMLTemplateElement).content &&
39
- (element as HTMLTemplateElement).content.nodeType === 11 ? TemplateType.Template :
40
- TemplateType.Element;
41
- }
42
-
43
- text(): string;
44
- text(value: string): void;
45
- text(value?: string): string | void {
46
- const prop = this.templateType === TemplateType.Script ? 'text'
47
- : this.templateType === TemplateType.TextArea ? 'value'
48
- : 'innerHTML';
49
-
50
- if (arguments.length === 0) {
51
- return (this.domElement as unknown as Record<string, unknown>)[prop] as string;
52
- } else {
53
- (this.domElement as unknown as Record<string, unknown>)[prop] = value;
54
- }
55
- }
56
-
57
- data(key: string): unknown;
58
- data(key: string, value: unknown): void;
59
- data(key: string, value?: unknown): unknown | void {
60
- if (arguments.length === 1) {
61
- return domDataGet(this.domElement, dataDomDataPrefix + key);
62
- } else {
63
- domDataSet(this.domElement, dataDomDataPrefix + key, value);
64
- }
65
- }
66
-
67
- nodes(): DocumentFragment | HTMLElement | undefined;
68
- nodes(value: DocumentFragment | HTMLElement): void;
69
- nodes(value?: DocumentFragment | HTMLElement): DocumentFragment | HTMLElement | undefined | void {
70
- const element = this.domElement;
71
- if (arguments.length === 0) {
72
- const templateData = getTemplateDomData(element);
73
- let nodes = templateData.containerData || (
74
- this.templateType === TemplateType.Template ? (element as HTMLTemplateElement).content :
75
- this.templateType === TemplateType.Element ? element as HTMLElement :
76
- undefined
77
- );
78
-
79
- if (!nodes || templateData.alwaysCheckText) {
80
- const text = this.text();
81
- if (text && text !== templateData.textData) {
82
- const parsed = parseHtmlFragment(text, element.ownerDocument);
83
- const container = element.ownerDocument.createElement('div');
84
- for (const n of parsed) container.appendChild(n);
85
- setTemplateDomData(element, {
86
- containerData: container,
87
- textData: text,
88
- alwaysCheckText: true,
89
- });
90
- nodes = container;
91
- }
92
- }
93
- return nodes;
94
- } else {
95
- const templateData = getTemplateDomData(element);
96
- templateData.containerData = value;
97
- setTemplateDomData(element, templateData);
98
- }
99
- }
100
- }
101
-
102
- export class AnonymousSource extends DomElementSource {
103
- constructor(element: Element | Comment) {
104
- super(element as Element);
105
- }
106
-
107
- override text(): string;
108
- override text(value: string): void;
109
- override text(value?: string): string | void {
110
- if (arguments.length === 0) {
111
- const data = domDataGet(this.domElement, dataDomDataPrefix + 'anonymousTemplateText') as string | undefined;
112
- if (data === undefined) {
113
- const nodesContainer = this.nodes();
114
- if (nodesContainer) {
115
- return (nodesContainer as HTMLElement).innerHTML;
116
- }
117
- }
118
- return data as string;
119
- } else {
120
- domDataSet(this.domElement, dataDomDataPrefix + 'anonymousTemplateText', value);
121
- }
122
- }
123
-
124
- override nodes(): DocumentFragment | HTMLElement | undefined;
125
- override nodes(value: DocumentFragment | HTMLElement): void;
126
- override nodes(value?: DocumentFragment | HTMLElement): DocumentFragment | HTMLElement | undefined | void {
127
- if (arguments.length === 0) {
128
- const containerData = getTemplateDomData(this.domElement).containerData;
129
- return containerData;
130
- } else {
131
- setTemplateDomData(this.domElement, { containerData: value });
132
- }
133
- }
134
- }
1
+ import { domDataGet, domDataSet, domDataNextKey } from './domData.js';
2
+ import { parseHtmlFragment } from './utilsDom.js';
3
+
4
+ const enum TemplateType {
5
+ Script = 1,
6
+ TextArea = 2,
7
+ Template = 3,
8
+ Element = 4,
9
+ }
10
+
11
+ const dataDomDataPrefix = domDataNextKey();
12
+ const templatesDomDataKey = domDataNextKey();
13
+
14
+ interface TemplateDomData {
15
+ containerData?: DocumentFragment | HTMLElement;
16
+ alwaysCheckText?: boolean;
17
+ textData?: string;
18
+ }
19
+
20
+ function getTemplateDomData(element: Node): TemplateDomData {
21
+ return (domDataGet(element, templatesDomDataKey) as TemplateDomData) || {};
22
+ }
23
+
24
+ function setTemplateDomData(element: Node, data: TemplateDomData): void {
25
+ domDataSet(element, templatesDomDataKey, data);
26
+ }
27
+
28
+ export class DomElementSource {
29
+ readonly domElement: Element;
30
+ private templateType: TemplateType;
31
+
32
+ constructor(element: Element) {
33
+ this.domElement = element;
34
+ const tagName = element.tagName?.toLowerCase();
35
+ this.templateType =
36
+ tagName === 'script' ? TemplateType.Script :
37
+ tagName === 'textarea' ? TemplateType.TextArea :
38
+ tagName === 'template' && (element as HTMLTemplateElement).content &&
39
+ (element as HTMLTemplateElement).content.nodeType === 11 ? TemplateType.Template :
40
+ TemplateType.Element;
41
+ }
42
+
43
+ text(): string;
44
+ text(value: string): void;
45
+ text(value?: string): string | void {
46
+ const prop = this.templateType === TemplateType.Script ? 'text'
47
+ : this.templateType === TemplateType.TextArea ? 'value'
48
+ : 'innerHTML';
49
+
50
+ if (arguments.length === 0) {
51
+ return (this.domElement as unknown as Record<string, unknown>)[prop] as string;
52
+ } else {
53
+ (this.domElement as unknown as Record<string, unknown>)[prop] = value;
54
+ }
55
+ }
56
+
57
+ data(key: string): unknown;
58
+ data(key: string, value: unknown): void;
59
+ data(key: string, value?: unknown): unknown | void {
60
+ if (arguments.length === 1) {
61
+ return domDataGet(this.domElement, dataDomDataPrefix + key);
62
+ } else {
63
+ domDataSet(this.domElement, dataDomDataPrefix + key, value);
64
+ }
65
+ }
66
+
67
+ nodes(): DocumentFragment | HTMLElement | undefined;
68
+ nodes(value: DocumentFragment | HTMLElement): void;
69
+ nodes(value?: DocumentFragment | HTMLElement): DocumentFragment | HTMLElement | undefined | void {
70
+ const element = this.domElement;
71
+ if (arguments.length === 0) {
72
+ const templateData = getTemplateDomData(element);
73
+ let nodes = templateData.containerData || (
74
+ this.templateType === TemplateType.Template ? (element as HTMLTemplateElement).content :
75
+ this.templateType === TemplateType.Element ? element as HTMLElement :
76
+ undefined
77
+ );
78
+
79
+ if (!nodes || templateData.alwaysCheckText) {
80
+ const text = this.text();
81
+ if (text && text !== templateData.textData) {
82
+ const parsed = parseHtmlFragment(text, element.ownerDocument);
83
+ const container = element.ownerDocument.createElement('div');
84
+ for (const n of parsed) container.appendChild(n);
85
+ setTemplateDomData(element, {
86
+ containerData: container,
87
+ textData: text,
88
+ alwaysCheckText: true,
89
+ });
90
+ nodes = container;
91
+ }
92
+ }
93
+ return nodes;
94
+ } else {
95
+ const templateData = getTemplateDomData(element);
96
+ templateData.containerData = value;
97
+ setTemplateDomData(element, templateData);
98
+ }
99
+ }
100
+ }
101
+
102
+ export class AnonymousSource extends DomElementSource {
103
+ constructor(element: Element | Comment) {
104
+ super(element as Element);
105
+ }
106
+
107
+ override text(): string;
108
+ override text(value: string): void;
109
+ override text(value?: string): string | void {
110
+ if (arguments.length === 0) {
111
+ const data = domDataGet(this.domElement, dataDomDataPrefix + 'anonymousTemplateText') as string | undefined;
112
+ if (data === undefined) {
113
+ const nodesContainer = this.nodes();
114
+ if (nodesContainer) {
115
+ return (nodesContainer as HTMLElement).innerHTML;
116
+ }
117
+ }
118
+ return data as string;
119
+ } else {
120
+ domDataSet(this.domElement, dataDomDataPrefix + 'anonymousTemplateText', value);
121
+ }
122
+ }
123
+
124
+ override nodes(): DocumentFragment | HTMLElement | undefined;
125
+ override nodes(value: DocumentFragment | HTMLElement): void;
126
+ override nodes(value?: DocumentFragment | HTMLElement): DocumentFragment | HTMLElement | undefined | void {
127
+ if (arguments.length === 0) {
128
+ const containerData = getTemplateDomData(this.domElement).containerData;
129
+ return containerData;
130
+ } else {
131
+ setTemplateDomData(this.domElement, { containerData: value });
132
+ }
133
+ }
134
+ }