From 118c370f8d7bc72a8e50c9907a2b66bf5db0a096 Mon Sep 17 00:00:00 2001
From: Volker Schukai <volker.schukai@schukai.com>
Date: Tue, 17 Aug 2021 12:20:55 +0200
Subject: [PATCH] #33

---
 packages/monster/source/data/transformer.js | 104 +++++++++++---------
 1 file changed, 59 insertions(+), 45 deletions(-)

diff --git a/packages/monster/source/data/transformer.js b/packages/monster/source/data/transformer.js
index 50ad518f3..74c5cfeed 100644
--- a/packages/monster/source/data/transformer.js
+++ b/packages/monster/source/data/transformer.js
@@ -6,7 +6,8 @@
 
 import {Monster} from '../namespace.js';
 import {Base} from '../types/base.js';
-import {validateString, validatePrimitive, validateFunction, validateInteger} from '../types/validate.js';
+import {getGlobal} from "../types/global.js";
+import {validateString, validatePrimitive, validateFunction, validateInteger, validateObject} from '../types/validate.js';
 import {isObject, isString, isArray} from '../types/is.js';
 import {ID} from '../types/id.js';
 import {clone} from "../util/clone.js";
@@ -34,15 +35,15 @@ import {Pathfinder} from "./pathfinder.js";
  * ```
  *
  * A simple example is the conversion of all characters to lowercase. for this purpose the command tolower must be used.
- * 
+ *
  * ```
  * let t = new Transformer('tolower').run('ABC'); // ↦ abc
  * ```
- * 
+ *
  * **all commands**
- * 
+ *
  * in the following table all commands, parameters and existing aliases are described.
- * 
+ *
  *  | command      | parameter                  | alias                   | description                                                                                                                                                                                                                                                                                                                                                |
  *  |:-------------|:---------------------------|:------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
  *  | base64       |                            |                         | Converts the value to base64                                                                                                                                                                                                                                                                                                                               |
@@ -69,9 +70,9 @@ import {Pathfinder} from "./pathfinder.js";
  *  | ucwords      |                            |                         | Any word beginning large                                                                                                                                                                                                                                                                                                                                   |
  *  | undefined    |                            |                         | Return undefined                                                                                                                                                                                                                                                                                                                                           |
  *  | uniqid       |                            |                         | Creates a string with a unique value (**)                                                                                                                                                                                                                                                                                                                  |
- * 
+ *
  *  (*) for this functionality the extension [jsdom](https://www.npmjs.com/package/jsdom) must be loaded in the nodejs context.
- * 
+ *
  * ```
  *  // polyfill
  *  if (typeof window !== "object") {
@@ -95,26 +96,26 @@ import {Pathfinder} from "./pathfinder.js";
  *     ].forEach(key => (global[key] = window[key]));
  * }
  * ```
- * 
+ *
  * (**) for this command the crypt library is necessary in the nodejs context.
- * 
+ *
  * ```
  * import * as Crypto from "@peculiar/webcrypto";
  * global['crypto'] = new Crypto.Crypto();
  * ```
- * 
+ *
  * @example
- * 
+ *
  * import {Transformer} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.9.0/dist/modules/data/transformer.js';
- * 
+ *
  * const transformer = new Transformer("tolower")
- * 
+ *
  * console.log(transformer.run("HELLO"))
  * // ↦ hello
- * 
+ *
  * console.log(transformer.run("WORLD"))
  * // ↦ world
- * 
+ *
  * @since 1.5.0
  * @copyright schukai GmbH
  * @memberOf Monster/Data
@@ -138,14 +139,24 @@ class Transformer extends Base {
      *
      * @param {string} name
      * @param {function} callback
+     * @param {object} context
      * @returns {Transformer}
      * @throws {TypeError} value is not a string
      * @throws {TypeError} value is not a function
      */
-    setCallback(name, callback) {
+    setCallback(name, callback, context) {
         validateString(name)
         validateFunction(callback)
-        this.callbacks.set(name, callback);
+        
+        if(context!==undefined) {
+            validateObject(context);
+        }
+        
+        this.callbacks.set(name, {
+            callback: callback,
+            context: context,
+        });
+        
         return this;
     }
 
@@ -174,40 +185,40 @@ export {Monster, Transformer}
 function disassemble(command) {
 
     validateString(command);
-    
+
     let placeholder = new Map;
     const regex = /((?<pattern>\\(?<char>.)){1})/mig;
 
     // The separator for args must be quotable
     // undefined string which should not occur normally and is also not a regex
     let result = command.matchAll(regex)
-    
+
     for (let m of result) {
-        let g=m?.['groups'];
-        if(!isObject(g)) {
+        let g = m?.['groups'];
+        if (!isObject(g)) {
             continue;
         }
-        
-        let p=g?.['pattern'];
-        let c=g?.['char'];
-        
-        if(p&&c) {
-            let r='__'+new ID().toString()+'__';
+
+        let p = g?.['pattern'];
+        let c = g?.['char'];
+
+        if (p && c) {
+            let r = '__' + new ID().toString() + '__';
             placeholder.set(r, c);
-            command=command.replace(p,r);
+            command = command.replace(p, r);
         }
-        
+
     }
     let parts = command.split(':');
 
     parts = parts.map(function (value) {
-        let v =  value.trim();
-        for(let k of placeholder) {
-           v= v.replace(k[0], k[1]);
+        let v = value.trim();
+        for (let k of placeholder) {
+            v = v.replace(k[0], k[1]);
         }
         return v;
-        
-        
+
+
     });
 
     return parts
@@ -215,7 +226,7 @@ function disassemble(command) {
 
 /**
  * tries to make a string out of value and if this succeeds to return it back
- * 
+ *
  * @param {*} value
  * @returns {string}
  * @private
@@ -268,7 +279,7 @@ function transform(value) {
             let n = parseInt(value);
             validateInteger(n);
             return n
-        
+
         case 'tojson':
             return JSON.stringify(value);
 
@@ -297,18 +308,21 @@ function transform(value) {
 
             let callback;
             let callbackName = args.shift();
+            let context = getGlobal();
 
             if (isObject(value) && value.hasOwnProperty(callbackName)) {
                 callback = value[callbackName];
             } else if (this.callbacks.has(callbackName)) {
-                callback = this.callbacks.get(callbackName);
+                let s = this.callbacks.get(callbackName);
+                callback = s?.['callback'];
+                context = s?.['context'];
             } else if (typeof window === 'object' && window.hasOwnProperty(callbackName)) {
                 callback = window[callbackName];
             }
             validateFunction(callback);
 
             args.unshift(value);
-            return callback(...args);
+            return callback.call(context, ...args);
 
         case  'plain':
         case  'plaintext':
@@ -393,13 +407,13 @@ function transform(value) {
             let defaultValue = (args.shift() || '');
 
             if (value instanceof Map) {
-                if(!value.has(key)) {
+                if (!value.has(key)) {
                     return defaultValue;
                 }
                 return value.get(key);
             }
 
-            if (isObject(value)||isArray(value)) {
+            if (isObject(value) || isArray(value)) {
 
                 if (value?.[key]) {
                     return value?.[key];
@@ -414,22 +428,22 @@ function transform(value) {
 
             key = (args.shift() || 'undefined');
             return new Pathfinder(value).getVia(key);
-            
-            
+
+
         case 'substring':
 
             validateString(value);
-            
+
             let start = parseInt(args[0]) || 0;
             let end = (parseInt(args[1]) || 0) + start;
 
             return value.substring(start, end);
-            
+
         case 'nop':
             return value;
 
         default:
-            throw new Error("unknown command "+this.command)
+            throw new Error("unknown command " + this.command)
     }
 
     return value;
-- 
GitLab