@tko/provider.mustache 4.0.0-alpha8.4 → 4.0.0-beta1.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.
@@ -0,0 +1,75 @@
1
+ // @tko/provider.mustache 🥊 4.0.0-beta1.3 ESM
2
+ import {
3
+ unwrap
4
+ } from "@tko/observable";
5
+ import {
6
+ Provider
7
+ } from "@tko/provider";
8
+ import {
9
+ parseInterpolation
10
+ } from "./mustacheParser";
11
+ const DEFAULT_ATTRIBUTE_BINDING_MAP = {
12
+ value: "value",
13
+ checked: "checked",
14
+ class: "css"
15
+ };
16
+ export default class AttributeMustacheProvider extends Provider {
17
+ get FOR_NODE_TYPES() {
18
+ return [1];
19
+ }
20
+ constructor(params = {}) {
21
+ super(params);
22
+ this.ATTRIBUTES_TO_SKIP = new Set(params.attributesToSkip || ["data-bind"]);
23
+ this.ATTRIBUTES_BINDING_MAP = params.attributesBindingMap || DEFAULT_ATTRIBUTE_BINDING_MAP;
24
+ }
25
+ *attributesToInterpolate(attributes) {
26
+ for (const attr of Array.from(attributes)) {
27
+ if (this.ATTRIBUTES_TO_SKIP.has(attr.name)) {
28
+ continue;
29
+ }
30
+ if (attr.specified && attr.value.includes("{{")) {
31
+ yield attr;
32
+ }
33
+ }
34
+ }
35
+ nodeHasBindings(node) {
36
+ return !this.attributesToInterpolate(node.attributes).next().done;
37
+ }
38
+ partsTogether(parts, context, node, ...valueToWrite) {
39
+ if (parts.length > 1) {
40
+ return parts.map((p) => unwrap(p.asAttr(context, this.globals, node))).join("");
41
+ }
42
+ const part = parts[0].asAttr(context, this.globals);
43
+ if (valueToWrite.length) {
44
+ part(valueToWrite[0]);
45
+ }
46
+ return part;
47
+ }
48
+ attributeBinding(name, parts) {
49
+ return [name, parts];
50
+ }
51
+ *bindingParts(node, context) {
52
+ for (const attr of this.attributesToInterpolate(node.attributes)) {
53
+ const parts = Array.from(parseInterpolation(attr.value));
54
+ if (parts.length) {
55
+ yield this.attributeBinding(attr.name, parts);
56
+ }
57
+ }
58
+ }
59
+ getPossibleDirectBinding(attrName) {
60
+ const bindingName = this.ATTRIBUTES_BINDING_MAP[attrName];
61
+ return bindingName && this.bindingHandlers.get(attrName);
62
+ }
63
+ *bindingObjects(node, context) {
64
+ for (const [attrName, parts] of this.bindingParts(node, context)) {
65
+ const bindingForAttribute = this.getPossibleDirectBinding(attrName);
66
+ const handler = bindingForAttribute ? attrName : `attr.${attrName}`;
67
+ const accessorFn = bindingForAttribute ? (...v) => this.partsTogether(parts, context, node, ...v) : (...v) => ({ [attrName]: this.partsTogether(parts, context, node, ...v) });
68
+ node.removeAttribute(attrName);
69
+ yield { [handler]: accessorFn };
70
+ }
71
+ }
72
+ getBindingAccessors(node, context) {
73
+ return Object.assign({}, ...this.bindingObjects(node, context));
74
+ }
75
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/AttributeMustacheProvider.ts"],
4
+ "sourcesContent": ["\nimport {\n unwrap\n} from '@tko/observable'\n\nimport {\n Provider\n} from '@tko/provider'\n\nimport {\n parseInterpolation\n} from './mustacheParser'\n\n/**\n * These are bindings that are mapped specific attributes, such as\n * two-way communication (value/checked) or which have anti-collision\n * properties (css).\n */\nconst DEFAULT_ATTRIBUTE_BINDING_MAP = {\n value: 'value',\n checked: 'checked',\n class: 'css'\n}\n\n/**\n * Interpret {{ }} inside DOM attributes e.g. <div class='{{ classes }}'>\n */\nexport default class AttributeMustacheProvider extends Provider {\n get FOR_NODE_TYPES () { return [ 1 ] } // document.ELEMENT_NODE\n\n constructor (params = {}) {\n super(params)\n this.ATTRIBUTES_TO_SKIP = new Set(params.attributesToSkip || ['data-bind'])\n this.ATTRIBUTES_BINDING_MAP = params.attributesBindingMap || DEFAULT_ATTRIBUTE_BINDING_MAP\n }\n\n * attributesToInterpolate (attributes) {\n for (const attr of Array.from(attributes)) {\n if (this.ATTRIBUTES_TO_SKIP.has(attr.name)) { continue }\n if (attr.specified && attr.value.includes('{{')) { yield attr }\n }\n }\n\n nodeHasBindings (node) {\n return !this.attributesToInterpolate(node.attributes).next().done\n }\n\n partsTogether (parts, context, node, ...valueToWrite) {\n if (parts.length > 1) {\n return parts\n .map(p => unwrap(p.asAttr(context, this.globals, node))).join('')\n }\n // It may be a writeable observable e.g. value=\"{{ value }}\".\n const part = parts[0].asAttr(context, this.globals)\n if (valueToWrite.length) { part(valueToWrite[0]) }\n return part\n }\n\n attributeBinding (name, parts) {\n return [name, parts]\n }\n\n * bindingParts (node, context) {\n for (const attr of this.attributesToInterpolate(node.attributes)) {\n const parts = Array.from(parseInterpolation(attr.value))\n if (parts.length) { yield this.attributeBinding(attr.name, parts) }\n }\n }\n\n getPossibleDirectBinding (attrName) {\n const bindingName = this.ATTRIBUTES_BINDING_MAP[attrName]\n return bindingName && this.bindingHandlers.get(attrName)\n }\n\n * bindingObjects (node, context) {\n for (const [attrName, parts] of this.bindingParts(node, context)) {\n const bindingForAttribute = this.getPossibleDirectBinding(attrName)\n const handler = bindingForAttribute ? attrName : `attr.${attrName}`\n const accessorFn = bindingForAttribute\n ? (...v) => this.partsTogether(parts, context, node, ...v)\n : (...v) => ({[attrName]: this.partsTogether(parts, context, node, ...v)})\n node.removeAttribute(attrName)\n yield { [handler]: accessorFn }\n }\n }\n\n getBindingAccessors (node, context) {\n return Object.assign({}, ...this.bindingObjects(node, context))\n }\n}\n"],
5
+ "mappings": ";AACA;AAAA;AAAA;AAIA;AAAA;AAAA;AAIA;AAAA;AAAA;AASA,MAAM,gCAAgC;AAAA,EACpC,OAAO;AAAA,EACP,SAAS;AAAA,EACT,OAAO;AACT;AAKA,qBAAqB,kCAAkC,SAAS;AAAA,MAC1D,iBAAkB;AAAE,WAAO,CAAE,CAAE;AAAA,EAAE;AAAA,EAErC,YAAa,SAAS,CAAC,GAAG;AACxB,UAAM,MAAM;AACZ,SAAK,qBAAqB,IAAI,IAAI,OAAO,oBAAoB,CAAC,WAAW,CAAC;AAC1E,SAAK,yBAAyB,OAAO,wBAAwB;AAAA,EAC/D;AAAA,GAEE,wBAAyB,YAAY;AACrC,eAAW,QAAQ,MAAM,KAAK,UAAU,GAAG;AACzC,UAAI,KAAK,mBAAmB,IAAI,KAAK,IAAI,GAAG;AAAE;AAAA,MAAS;AACvD,UAAI,KAAK,aAAa,KAAK,MAAM,SAAS,IAAI,GAAG;AAAE,cAAM;AAAA,MAAK;AAAA,IAChE;AAAA,EACF;AAAA,EAEA,gBAAiB,MAAM;AACrB,WAAO,CAAC,KAAK,wBAAwB,KAAK,UAAU,EAAE,KAAK,EAAE;AAAA,EAC/D;AAAA,EAEA,cAAe,OAAO,SAAS,SAAS,cAAc;AACpD,QAAI,MAAM,SAAS,GAAG;AACpB,aAAO,MACJ,IAAI,OAAK,OAAO,EAAE,OAAO,SAAS,KAAK,SAAS,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE;AAAA,IACpE;AAEA,UAAM,OAAO,MAAM,GAAG,OAAO,SAAS,KAAK,OAAO;AAClD,QAAI,aAAa,QAAQ;AAAE,WAAK,aAAa,EAAE;AAAA,IAAE;AACjD,WAAO;AAAA,EACT;AAAA,EAEA,iBAAkB,MAAM,OAAO;AAC7B,WAAO,CAAC,MAAM,KAAK;AAAA,EACrB;AAAA,GAEE,aAAc,MAAM,SAAS;AAC7B,eAAW,QAAQ,KAAK,wBAAwB,KAAK,UAAU,GAAG;AAChE,YAAM,QAAQ,MAAM,KAAK,mBAAmB,KAAK,KAAK,CAAC;AACvD,UAAI,MAAM,QAAQ;AAAE,cAAM,KAAK,iBAAiB,KAAK,MAAM,KAAK;AAAA,MAAE;AAAA,IACpE;AAAA,EACF;AAAA,EAEA,yBAA0B,UAAU;AAClC,UAAM,cAAc,KAAK,uBAAuB;AAChD,WAAO,eAAe,KAAK,gBAAgB,IAAI,QAAQ;AAAA,EACzD;AAAA,GAEE,eAAgB,MAAM,SAAS;AAC/B,eAAW,CAAC,UAAU,UAAU,KAAK,aAAa,MAAM,OAAO,GAAG;AAChE,YAAM,sBAAsB,KAAK,yBAAyB,QAAQ;AAClE,YAAM,UAAU,sBAAsB,WAAW,QAAQ;AACzD,YAAM,aAAa,sBACf,IAAI,MAAM,KAAK,cAAc,OAAO,SAAS,MAAM,GAAG,CAAC,IACvD,IAAI,MAAO,IAAE,WAAW,KAAK,cAAc,OAAO,SAAS,MAAM,GAAG,CAAC,EAAC;AAC1E,WAAK,gBAAgB,QAAQ;AAC7B,YAAM,GAAG,UAAU,WAAW;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,oBAAqB,MAAM,SAAS;AAClC,WAAO,OAAO,OAAO,CAAC,GAAG,GAAG,KAAK,eAAe,MAAM,OAAO,CAAC;AAAA,EAChE;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,41 @@
1
+ // @tko/provider.mustache 🥊 4.0.0-beta1.3 ESM
2
+ import {
3
+ Provider
4
+ } from "@tko/provider";
5
+ import {
6
+ parseInterpolation
7
+ } from "./mustacheParser";
8
+ export default class TextMustacheProvider extends Provider {
9
+ get FOR_NODE_TYPES() {
10
+ return [3];
11
+ }
12
+ *textToNodes(textNode) {
13
+ const parent = textNode.parentNode;
14
+ const isTextarea = parent && parent.nodeName === "TEXTAREA";
15
+ const hasStash = textNode.nodeValue && textNode.nodeValue.includes("{{");
16
+ if (!hasStash || isTextarea) {
17
+ return;
18
+ }
19
+ for (const part of parseInterpolation(textNode.nodeValue)) {
20
+ yield* part.textNodeReplacement(textNode);
21
+ }
22
+ }
23
+ textInterpolation(textNode) {
24
+ const newNodes = Array.from(this.textToNodes(textNode));
25
+ if (newNodes.length === 0) {
26
+ return;
27
+ }
28
+ if (textNode.parentNode) {
29
+ const parent = textNode.parentNode;
30
+ const n = newNodes.length;
31
+ for (let i = 0; i < n; ++i) {
32
+ parent.insertBefore(newNodes[i], textNode);
33
+ }
34
+ parent.removeChild(textNode);
35
+ }
36
+ return newNodes;
37
+ }
38
+ preprocessNode(node) {
39
+ return this.textInterpolation(node);
40
+ }
41
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/TextMustacheProvider.ts"],
4
+ "sourcesContent": ["import {\n Provider\n} from '@tko/provider'\n\nimport {\n parseInterpolation\n} from './mustacheParser'\n\n/**\n * Interpret {{ }}, {{{ }}}, {{# /}}, and {{# }} ... {{/ }} inside text nodes.\n *\n * This binding must come before the VirtualProvider.\n */\nexport default class TextMustacheProvider extends Provider {\n get FOR_NODE_TYPES () { return [ 3 ] } // document.TEXT_NODE\n\n * textToNodes (textNode) {\n const parent = textNode.parentNode\n const isTextarea = parent && parent.nodeName === 'TEXTAREA'\n const hasStash = textNode.nodeValue && textNode.nodeValue.includes('{{')\n\n if (!hasStash || isTextarea) { return }\n\n for (const part of parseInterpolation(textNode.nodeValue)) {\n yield * part.textNodeReplacement(textNode)\n }\n }\n\n textInterpolation (textNode) {\n const newNodes = Array.from(this.textToNodes(textNode))\n\n if (newNodes.length === 0) { return }\n\n if (textNode.parentNode) {\n const parent = textNode.parentNode\n const n = newNodes.length\n for (let i = 0; i < n; ++i) {\n parent.insertBefore(newNodes[i], textNode)\n }\n parent.removeChild(textNode)\n }\n\n return newNodes\n }\n\n /**\n * We convert as follows:\n *\n * {{# ... }} into <!-- ko ... -->\n * {{/ ... }} into <!-- /ko -->\n * {{# ... /}} into <!-- ko ... --><!-- /ko -->\n * {{ ... }} into <!-- ko text: ... --><!-- /ko -->\n * {{{ ... }}} into <!-- ko html: ... --><!-- /ko -->\n *\n * VirtualProvider can then pick up and do the actual binding.\n */\n preprocessNode (node) {\n return this.textInterpolation(node)\n }\n}\n"],
5
+ "mappings": ";AAAA;AAAA;AAAA;AAIA;AAAA;AAAA;AASA,qBAAqB,6BAA6B,SAAS;AAAA,MACrD,iBAAkB;AAAE,WAAO,CAAE,CAAE;AAAA,EAAE;AAAA,GAEnC,YAAa,UAAU;AACvB,UAAM,SAAS,SAAS;AACxB,UAAM,aAAa,UAAU,OAAO,aAAa;AACjD,UAAM,WAAW,SAAS,aAAa,SAAS,UAAU,SAAS,IAAI;AAEvE,QAAI,CAAC,YAAY,YAAY;AAAE;AAAA,IAAO;AAEtC,eAAW,QAAQ,mBAAmB,SAAS,SAAS,GAAG;AACzD,aAAQ,KAAK,oBAAoB,QAAQ;AAAA,IAC3C;AAAA,EACF;AAAA,EAEA,kBAAmB,UAAU;AAC3B,UAAM,WAAW,MAAM,KAAK,KAAK,YAAY,QAAQ,CAAC;AAEtD,QAAI,SAAS,WAAW,GAAG;AAAE;AAAA,IAAO;AAEpC,QAAI,SAAS,YAAY;AACvB,YAAM,SAAS,SAAS;AACxB,YAAM,IAAI,SAAS;AACnB,eAAS,IAAI,GAAG,IAAI,GAAG,EAAE,GAAG;AAC1B,eAAO,aAAa,SAAS,IAAI,QAAQ;AAAA,MAC3C;AACA,aAAO,YAAY,QAAQ;AAAA,IAC7B;AAEA,WAAO;AAAA,EACT;AAAA,EAaA,eAAgB,MAAM;AACpB,WAAO,KAAK,kBAAkB,IAAI;AAAA,EACpC;AACF;",
6
+ "names": []
7
+ }