How to use transformNode method in Cucumber-gherkin

Best JavaScript code snippet using cucumber-gherkin

XsltContext.js

Source:XsltContext.js Github

copy

Full Screen

1/*2 * @file XsltContext.js - An XSLT engine written in JavaScript.3 * @author {@link mailto:grant.vergottini@xcential.com Grant Vergottini}4 * @author {@link mailto:mesch@google.com Steffen Meschkat} (Original)5 * @version 1.06 * @copyright &copy; 2019 -- {@link http://xcential.com Xcential Corp.}7 * @copyright &copy; 2005 Google Inc.8 *9 */10'use strict';11// ----------------------------------------------------------------------------12// Imports13// ----------------------------------------------------------------------------14const XmlDOM = require('xmldom');15const XPath = require('xpath');16const { $$ } = require('./XDomHelper');17const { Node } = require('./Node');18const { XPathNamespaceResolver } = require('./XPathNamespaceResolver');19const { XPathVariableResolver } = require('./XPathVariableResolver');20const { XPathFunctionResolver } = require('./XPathFunctionResolver');21const { Utils } = require('./Utils');22const { XsltLog } = require('./XsltLog');23// ----------------------------------------------------------------------------24/* @class XsltContext25 * @classdesc Context object for evaluating XSLT elements.26 */27var XsltContext = class {28  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -29  /*30   * @constructor31   * @param {Node} contextNode - The node in the source document to use as the context.32   * @param {Object} [options={}] - Other settings to be used in the context33   */34  constructor (35    contextNode,36    options = {}37  ) {38    this.contextNode = contextNode;39    this.contextPosition = options.contextPosition || 1;40    this.nodeList = options.nodeList || [contextNode];41    this.variables = options.variables || {};42    this.inputURL = options.inputURL || null;43    this.transformURL = options.transformURL || null;44    this.customFunctions = options.customFunctions || {};45    this.mode = options.mode || null;46    this.parent = options.parent || null;47    this.cfg = options.cfg || {};48    this.logger = options.logger || XsltLog.logger;49    this.debug = (msg) => this.logger.debug('# XSLT: ' + (' ').repeat(XsltContext.indent * 2) + msg);50    this.logTransform = (node) => this.debug(Utils.identify(node));51    this.getContext = () => 'context node ' + (this.nodeList.length > 1 ? '#' + this.contextPosition + ' ' : '') + '-- ' + Utils.identify(this.contextNode);52    if (this.contextNode.nodeType === Node.DOCUMENT_NODE) {53      // NOTE(meschkat): DOM Spec stipulates that the ownerDocument of a54      // document is null. Our root, however is the document that we are55      // processing, so the initial context is created from its document56      // node, which case we must handle here explcitly.57      this.root = contextNode;58    } else {59      this.root = contextNode.ownerDocument;60    }61  }62  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -63  // Instance methods64  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -65  /*66   * Makes a copy of the current context, replace items that are specified.67   * @method clone68   * @instance69   * @param {Object} [options={}] - Optional parameters to use instead.70   */71  clone (72    options = {}73  ) {74    const clone = (variables) => {75      const clonedVariables = {};76      for (const key in variables) {77        clonedVariables[key] = variables[key];78      }79      return clonedVariables;80    };81    const context = new XsltContext(options.contextNode || this.contextNode, {82      contextPosition: options.contextPosition || this.contextPosition,83      nodeList: options.nodeList || this.nodeList,84      variables: (options.variables) ? clone(options.variables) : {},85      inputURL: options.inputURL || this.inputURL,86      transformURL: options.transformURL || this.transformURL,87      customFunctions: options.customFunctions || this.customFunctions,88      mode: options.mode || null, // This should not be inherited89      cfg: options.cfg || this.cfg,90      logger: options.logger || this.logger,91      parent: this92    });93    if (options.transformNode) {94      context.transformNode = options.transformNode;95      context.namespaceResolver = new XPathNamespaceResolver(context.transformNode);96      context.variableResolver = new XPathVariableResolver(context.transformNode, context);97      context.functionResolver = new XPathFunctionResolver(context.transformNode, context);98    }99    return context;100  }101  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -102  /*103   * Determines if a text node in the XSLT template document is to be104   * stripped according to XSLT whitespace stipping rules.105   * @method passText106   * @instance107   * @param {Node} transformNode - the XSLT node to use.108   * @returns {Boolean}109   * @see [XSLT], section 3.4.110   * @todo (meschkat) Whitespace stripping on the input document is111   *   currently not implemented.112   */113  passText (114    transformNode115  ) {116    if (!transformNode.nodeValue.match(/^\s*$/)) {117      return true;118    }119    let parentElement = transformNode.parentNode;120    if ($$(parentElement).isA('xsl:text')) {121      return true;122    }123    while (parentElement && parentElement.nodeType === Node.ELEMENT_NODE) {124      const xmlSpace = $$(parentElement).getAttribute('xml:space');125      if (xmlSpace) {126        if (xmlSpace === 'default') {127          return false;128        } else if (xmlSpace === 'preserve') {129          return true;130        }131      }132      parentElement = parentElement.parentNode;133    }134    return false;135  }136  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -137  /*138   * Passes template text to the output. The current template node does139   * not specify an XSLT operation and therefore is appended to the140   * output with all its attributes. Then continues traversing the141   * template node tree.142   * @method passThrough143   * @instance144   * @param {Node} transformNode - The node being evaluated.145   * @param {Node} outputNode - The document to apply the results to.146   */147  async passThrough (148    transformNode,149    outputNode150  ) {151    const outputDocument = outputNode.ownerDocument;152    switch (transformNode.nodeType) {153      case Node.DOCUMENT_NODE: {154        // This applies to the DOCUMENT_NODE of the XSL transform,155        // so we don't have to treat it specially.156        await this.processChildNodes(transformNode, outputNode);157        break;158      }159      case Node.ELEMENT_NODE: {160        const qName = transformNode.nodeName;161        const namespaceURI = transformNode.namespaceURI;162        const newElement = $$(outputDocument).createElementNS(namespaceURI, qName);163        $$(transformNode.attributes).forEach((attribute) => {164          const name = attribute.nodeName;165          const valueExpr = attribute.nodeValue;166          const value = this.resolveExpression(transformNode, valueExpr);167          newElement.setAttribute(name, value);168        });169        outputNode.appendChild(newElement);170        await this.processChildNodes(transformNode, newElement);171        break;172      }173      case Node.TEXT_NODE: {174        if (this.passText(transformNode)) {175          const text = $$(transformNode).textContent;176          const newTextNode = $$(outputDocument).createTextNode(text);177          outputNode.appendChild(newTextNode);178        }179        break;180      }181    }182  }183  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -184  getTemplateNode (185    document,186    name187  ) {188    const transformRoot = document.documentElement;189    if (!this.cfg._cache.templatesByName) {190      this.cfg._cache.templatesByName = {};191      $$(transformRoot.childNodes).forEach((childTransformNode) => {192        if ($$(childTransformNode).isA('xsl:template') &&193        childTransformNode.hasAttribute('name')) {194          this.cfg._cache.templatesByName[childTransformNode.getAttribute('name')] = childTransformNode;195        }196      });197    }198    return this.cfg._cache.templatesByName[name];199  }200  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -201  getTemplateNodes (202    document,203    mode = '_default'204  ) {205    const transformRoot = document.documentElement;206    if (!this.cfg._cache.templatesByMode) {207      this.cfg._cache.templatesByMode = {};208    }209    if (!this.cfg._cache.templatesByMode[mode]) {210      this.cfg._cache.templatesByMode[mode] = [];211      $$(transformRoot.childNodes).forEach((childTransformNode) => {212        if ($$(childTransformNode).isA('xsl:template') &&213            childTransformNode.hasAttribute('match') &&214            ((mode === '_default' && !childTransformNode.hasAttribute('mode')) || $$(childTransformNode).getAttribute('mode') === mode)) {215          this.cfg._cache.templatesByMode[mode].push(childTransformNode);216        }217      });218    }219    return this.cfg._cache.templatesByMode[mode];220  }221  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -222  /*223   * Evaluates an XSLT attribute value template. Attribute value224   * templates are attributes on XSLT elements that contain XPath225   * expressions in braces {}. The XSLT expressions are evaluated in226   * the current input context.227   * @method resolveExpression228   * @instance229   * @param {Node} transformNode - The node being evaluated.230   * @param {string} value - The text containing items to resolve.231   * @returns {string}232   */233  resolveExpression (234    transformNode,235    value236  ) {237    while ((/\{[^}]+\}/).test(value)) {238      const match = value.match(/^(.*?)\{([^{}]+)\}(.*)$/);239      const leftSide = match[1];240      const xPath = match[2];241      const rightSide = match[3];242      if ((/^[.$]/).test(xPath) || (/:\/\(/).testXPath) {243        try {244          const context = this.clone({ transformNode: transformNode });245          value = leftSide + this.processWhitespace($$(this.contextNode).select(xPath, context, { type: XPath.XPathResult.STRING_TYPE })) + rightSide;246        } catch (exception) {247          value = leftSide + '[[[' + xPath + ']]]' + rightSide;248        }249      } else {250        value = leftSide + '[[[' + xPath + ']]]' + rightSide;251      }252    }253    return value.replace(/\[\[\[/g, '{').replace(/]]]/g, '}');254  }255  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -256  /*257   * Finds a node with the specified name. Further filtering to an element tag258   * can be done via the options. Also, by default, the root node will be259   * searched, but an alternate transform context node can be specified.260   * @method findNamedNode261   * @instance262   * @param {string} name - The value of the name attribute to search for.263   * @param {Object} [options={}] - Specify a 'filter' as either an264   *   array or string value of qNames to filter against. Use a '^' at265   *   the start of a qName to invert the sense. Specify a 'context' as266   *   a node in the transform document. Otherwise, the documentElement267   *   will be used268   * @returns {Node|Null}269   */270  findNamedNode (271    transformNode,272    findName,273    options = {}274  ) {275    const filter = options.filter || null;276    const contextNode = options.root || transformNode.ownerDocument.documentElement;277    for (const childcontextNode of contextNode.childNodes) {278      if (childcontextNode.nodeType === Node.ELEMENT_NODE) {279        if (filter && !$$(childcontextNode).isA(filter)) {280          continue;281        }282        const name = $$(childcontextNode).getAttribute('name');283        if (name === findName) {284          return childcontextNode;285        } else if (name && options.namespaceURI) {286          const prefix = ((/:/).test(name)) ? name.replace(/:.*$/, '') : null;287          const namespaceURI = transformNode.lookupNamespaceURI(prefix);288          const localName = name.replace(/^.*:/, '');289          if (namespaceURI === options.namespaceURI && localName === findName) {290            return childcontextNode;291          }292        }293      }294    }295    return null;296  }297  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -298  /*299   * Process whitespace according to current rules.300   * @method processWhitespace301   * @instance302   * @param {string} value - The text value to process.303   * @param {Element} [contextElement=null] - the parent element to consider for304   *   whitespace rules. If not set, the value is treated as an attribute value305   *   and whitespace is stripped306   * @return {string}.307   */308  processWhitespace (309    value,310    contextElement = null311  ) {312    let process = 'strip'; // Default for attribute values313    if (contextElement) {314      const namespaceURI = contextElement.namespaceURI;315      const localName = contextElement.localName;316      const fullName = ((namespaceURI) ? '{' + namespaceURI + '}' : '') + localName;317      const allNamespace = (namespaceURI) ? '{' + namespaceURI + '}*' : null;318      if (this.cfg.stripSpaceList[fullName] || (allNamespace && this.cfg.stripSpaceList[allNamespace])) {319        process = 'strip';320      } else if (this.cfg.preserveSpaceList[fullName] || (allNamespace && this.cfg.preserveSpaceList[allNamespace])) {321        process = 'preserve';322      } else if (this.cfg.stripSpaceList['*']) {323        process = 'strip';324      } else if (this.cfg.preserveSpaceList['*']) {325        process = 'preserve';326      } else {327        process = 'normalize';328      }329    }330    if (typeof value === 'string') {331      switch (process) {332        case 'strip':333          value = value.replace(/(^[ \r\n\t\f]+|[ \r\n\t](?=[\s\r\n\t\f]+)|[ \r\n\t\f]+$)/g, '');334          break;335        case 'preserve':336          // Do nothing337          break;338        case 'normalize':339          value = value.replace(/[ \r\n\t\f]+/g, ' ');340          break;341      }342    }343    return value;344  }345  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -346  /*347   * Orders the current node list in the input context according to the348   * sort order specified by xsl:sort child nodes of the current349   * template node. This happens before the operation specified by the350   * current template node is executed.351   * @method sortNodes352   * @instance353   * @param {Node} transformNode - The node being evaluated.354   * @todo (meschkat) Case-order is not implemented.355   */356  sortNodes (357    transformNode358  ) {359    const sort = [];360    $$(transformNode.childNodes).forEach((childTransformNode) => {361      if ($$(childTransformNode).isA('xsl:sort')) {362        const select = $$(childTransformNode).getAttribute('select');363        const type = $$(childTransformNode).getAttribute('data-type') || 'text';364        const order = $$(childTransformNode).getAttribute('order') || 'ascending';365        sort.push({ select, type, order });366      }367    });368    if (sort.length === 0) {369      return;370    }371    const sortList = [];372    this.nodeList.forEach((contextNode, i) => {373      /* const context = */ this.clone({ contextNode: contextNode, contextPosition: 1, nodeList: [contextNode] });374      const sortItem = {375        contextNode,376        key: []377      };378      sort.forEach((sortItem) => {379        const context = this.clone({ transformNode: transformNode });380        const contextNodes = $$(context.contextNode).select(sortItem.select, context);381        let eValue;382        if (sortItem.type === 'text') {383          let value = '';384          contextNodes.forEach((contextNode) => {385            value += contextNode.textContent;386          });387          eValue = String(value);388        } else if (sortItem.type === 'number') {389          let value = '';390          contextNodes.forEach((contextNode) => {391            value += contextNode.textContent;392          });393          eValue = Number(value);394        }395        sortItem.key.push({396          value: eValue,397          order: sortItem.order398        });399      });400      // Make the sort stable by adding a lowest priority sort by401      // id. This is very convenient and furthermore required by the402      // spec ([XSLT] - Section 10 Sorting).403      sortItem.key.push({404        value: i,405        order: 'ascending'406      });407      sortList.push(sortItem);408    });409    // Sorts by all order criteria defined. According to the JavaScript410    // spec ([ECMA] Section 11.8.5), the compare operators compare strings411    // as strings and numbers as numbers.412    //413    // NOTE: In browsers which do not follow the spec, this breaks only in414    // the case that numbers should be sorted as strings, which is very415    // uncommon.416    sortList.sort((v1, v2) => {417      // NOTE: Sort key vectors of different length never occur in XSLT.sort().418      for (let i = 0; i < v1.key.length; ++i) {419        const o = v1.key[i].order === 'descending' ? -1 : 1;420        if (v1.key[i].value > v2.key[i].value) {421          return +1 * o;422        } else if (v1.key[i].value < v2.key[i].value) {423          return -1 * o;424        }425      }426      return 0;427    });428    const contextNodes = [];429    sortList.forEach((sortItem) => {430      contextNodes.push(sortItem.node);431    });432    this.nodeList = contextNodes;433    this.setNode(0);434  }435  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -436  /*437   * Stores a variable name/value part in this context.438   * @method setVariable439   * @instance440   * @param {string} name - The name of the variable to set.441   * @param {string|number|boolean|Array|Object} value - The value of the variable.442   */443  setVariable (444    name,445    value446  ) {447    if (typeof value === 'string') {448      if (value === 'true') {449        value = Boolean(true);450      } else if (value === 'false') {451        value = Boolean(false);452      } else if (new RegExp('^\\d+(\\.\\d*)?$').test(value)) {453        value = Number(value);454      } else {455        value = String(value);456      }457    }458    this.variables[name] = value;459  }460  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -461  /* Retrieves the value of a variable stored in this context, or in a parent462   * context.463   * @method getVariable464   * @instance465   * @method {string} name - The name of the variable to retrieve.466   * @returns {string|number|boolean|array|Object}467   */468  getVariable (469    name,470    options = {}471  ) {472    if (this.variables[name] !== undefined) {473      return this.variables[name];474    } else if (!options.localOnly && this.parent) {475      return this.parent.getVariable(name);476    } else {477      return null;478    }479  }480  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -481  /*482   * Evaluates a variable or parameter and set it in the current input483   * context. Used by implementation of <xsl:variable>, <xsl:param?, and484   * <xsl:with-param>.485   * @method processVariable486   * @instance487   * @param {Node} transformNode - The node being evaluated.488   * @param {Object} [options={}] - Options to configure out the variable489   *   is stored. Use .override to allow an existing variable to be overridden490   *   and use .asText to force the variable to be store as a string. Use491   *   .value to send a value that will take precedence over the node value.492   */493  async processVariable (494    transformNode,495    options = {}496  ) {497    const override = options.override || false;498    const asText = options.asText || false;499    const name = $$(transformNode).getAttribute('name');500    const select = $$(transformNode).getAttribute('select');501    const prevDebugMode = XsltLog.debugMode;502    try {503      if (transformNode.getAttribute('debug') === 'true') {504        XsltLog.debugMode = true;505        debugger;506      }507      let value = options.value || null;508      if (value === null) {509        if (transformNode.childNodes.length > 0) {510          const fragmentNode = transformNode.ownerDocument.createDocumentFragment();511          await this.processChildNodes(transformNode, fragmentNode);512          value = fragmentNode;513        } else if (select) {514          value = await this.xsltSelect(transformNode, select);515        } else if (this.variables[name] !== undefined) {516          value = this.variables[name];517        } else {518          value = '';519        }520      }521      if (override || !this.getVariable(name, { localOnly: true })) {522        value = (asText && (value instanceof Array || value.nodeType !== undefined)) ? $$(value).textContent : value;523        value = (typeof value === 'string') ? value.replace(/\s+/g, ' ') : value;524        this.setVariable(name, value);525      }526    } finally {527      XsltLog.debugMode = prevDebugMode;528    }529  }530  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -531  /*532   * Traverses the template node tree. Calls the main processing533   * function with the current input context for every child node of the534   * current template node.535   * @method processChildNodes536   * @instance537   * @param {Node} transformNode - The node being evaluated.538   * @param {string} match - The expression to evaluate539   */540  async processChildNodes (541    transformNode,542    outputNode,543    options = {}544  ) {545    if (outputNode.childNodes == null) {546      return false;547    }548    if (transformNode.childNodes.length === 0) {549      const newTextNode = $$(outputNode.ownerDocument).createTextNode('');550      outputNode.appendChild(newTextNode);551      return false;552    }553    for (let i = 0; i < transformNode.childNodes.length; i++) {554      const childTransformNode = transformNode.childNodes[i];555      if (options.ignoreText && childTransformNode.nodeType === Node.TEXT_NODE) {556        continue; // Don't break on return557      } else if (options.filter && !$$(childTransformNode).isA(options.filter)) {558        continue; // Don't break on return559      }560      switch (childTransformNode.nodeType) {561        case Node.ELEMENT_NODE: {562          await this.process(childTransformNode, outputNode);563          break;564        }565        case Node.TEXT_NODE: {566          const text = $$(childTransformNode).textContent;567          if (text.replace(/[ \r\n\f]/g, '').length > 0) {568            this.debug('- processing child ' + Utils.identify(childTransformNode) + ' transform node');569            const newTextNode = $$(outputNode.ownerDocument).createTextNode(text);570            outputNode.appendChild(newTextNode);571          } else if ((/^ +$/).test(text)) {572            const newTextNode = $$(outputNode.ownerDocument).createTextNode(' ');573            outputNode.appendChild(newTextNode);574          }575          break;576        }577      }578    }579  }580  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -581  /*582   * Remove all the include and import nodes and replace the content583   * referenced.584   * @instance585   * @param transformNode - The transform node containing the includes586   */587  async processIncludes (588    transformNode589  ) {590    for (var i = 0; i < transformNode.childNodes.length; i++) {591      const childTransformNode = transformNode.childNodes[i];592      if (childTransformNode.nodeType === Node.ELEMENT_NODE) {593        if ($$(childTransformNode).isA('xsl:include')) {594          await this.xsltInclude(childTransformNode);595        } else if ($$(childTransformNode).isA('xsl:import')) {596          await this.xsltImport(childTransformNode);597        }598      }599    }600  }601  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -602  /*603   * The main entry point of the XSLT processor, as explained above.604   * @method processRoot605   * @instance606   * @param transformNode - The transform document root, as a DOM node.607   * @param outputNode - The root of the generated output, as a DOM node.608   * @param {Object} [options={}] - Any options to pass to the implementation.609   *   Use the options to pass a parameter value610   */611  async processRoot (612    transformNode,613    outputNode,614    options = {}615  ) {616    const namespaceURI = transformNode.namespaceURI;617    const localName = transformNode.localName;618    let returnValue = null;619    const prevDebugMode = XsltLog.debugMode;620    try {621      if (transformNode.getAttribute('debug') === 'true') {622        XsltLog.debugMode = true;623        debugger;624      }625      if (namespaceURI !== new XPathNamespaceResolver(transformNode).getNamespace('xsl')) {626        await this.passThrough(transformNode, outputNode);627      } else {628        const functionName = 'xslt' + localName.replace(/^[a-z]|-[a-z]/gi, (match) => {629          return match.replace(/-/, '').toUpperCase();630        });631        if (this[functionName]) {632          const exec = async () => this[functionName](transformNode, outputNode, options);633          returnValue = (XsltLog.debugMode) ? await Utils.measureAsync(functionName, exec) : await exec();634        } else {635          throw new Error(`not implemented: ${localName}`);636        }637      }638    } finally {639      XsltLog.debugMode = prevDebugMode;640    }641    return returnValue;642  }643  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -644  /*645   * Processes a single transform node at the current context.646   * @method process647   * @instance648   * @param transformNode - The transform document root, as a DOM node.649   * @param outputNode - The root of the generated output, as a DOM node.650   * @param {Object} [options={}] - Any options to pass to the implementation.651   *   Use the options to pass a parameter value652   */653  async process (654    transformNode,655    outputNode,656    options = {}657  ) {658    const namespaceURI = transformNode.namespaceURI;659    const localName = transformNode.localName;660    let returnValue = null;661    const prevDebugMode = XsltLog.debugMode;662    try {663      if (transformNode.getAttribute('debug') === 'true') {664        XsltLog.debugMode = true;665        debugger;666      }667      if (namespaceURI !== new XPathNamespaceResolver(transformNode).getNamespace('xsl')) {668        await this.passThrough(transformNode, outputNode);669      } else {670        const functionName = 'xslt' + localName.replace(/^[a-z]|-[a-z]/gi, (match) => {671          return match.replace(/-/, '').toUpperCase();672        });673        if (this[functionName]) {674          const exec = async () => this[functionName](transformNode, outputNode, options);675          returnValue = (XsltLog.debugMode) ? await Utils.measureAsync(functionName, exec) : await exec();676        } else {677          throw new Error(`not implemented: ${localName}`);678        }679      }680    } finally {681      XsltLog.debugMode = prevDebugMode;682    }683    return returnValue;684  }685  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -686  // XSL Attribute & Element implementations687  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -688  /*689   * @method xsltMatch690   * @instance691   * @implements @match692   * @param {Node} transformNode - The node being evaluated.693   * @param {string} match - The expression to evaluate694   */695  xsltMatch (696    transformNode,697    match698  ) {699    const contextNode = this.contextNode.ownerElement || this.contextNode.parentNode || this.contextNode;700    const context = this.clone({ contextNode: contextNode, transformNode: transformNode });701    const matchNodes = $$(contextNode).select(match, context);702    for (const matchNode of matchNodes) {703      if (matchNode === this.contextNode) {704        return true;705      }706      if (this.contextNode.nodeType === Node.DOCUMENT_NODE && this.contextNode.documentElement === matchNode) {707        return true; // This is a bit of a kludge708      }709    }710    return false;711  }712  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -713  /*714   * @method xsltTest715   * @instance716   * @implements @test717   * @param {Node} transformNode - The node being evaluated.718   * @param {string} text - The expression to evaluate.719   */720  xsltTest (721    transformNode,722    test723  ) {724    let returnValue = false;725    const context = this.clone({ transformNode: transformNode });726    returnValue = $$(this.contextNode).select(test, context, { type: XPath.XPathResult.BOOLEAN_TYPE });727    return returnValue;728  }729  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -730  /*731   * @method xsltSelect732   * @instance733   * @implements @select734   * @param {Node} transformNode - The node being evaluated.735   * @param {Node} select - The expression to evaluate.736   * @param {XPath.XPathResult} [type=undefined] - The type of result to return.737   */738  async xsltSelect (739    transformNode,740    select,741    type = undefined742  ) {743    let contextNode = null;744    let variableNode = null;745    let value = null;746    // NOTE: XPath evaluation only works properly when the fragment is747    //       inserted into the document. So we do this temporarily.748    if ((/^\s*document\(\s*\$(.*?)\s*\)/).test(select)) {749      const srcVariable = select.replace(/^\s*document\(\s*\$(.*?)\s*\).*$/, '$1');750      const srcURL = (this.getVariable(srcVariable) || '').toString();751      const srcXML = await Utils.fetch(srcURL);752      if (srcXML) {753        const DOMParser = new XmlDOM.DOMParser();754        const srcDoc = DOMParser.parseFromString(srcXML);755        const documentNode = (this.contextNode.nodeType === Node.DOCUMENT_NODE) ? this.contextNode : this.contextNode.ownerDocument;756        contextNode = documentNode.createElement('temp');757        for (let i = 0; i < srcDoc.childNodes.length; i++) {758          const srcNode = srcDoc.childNodes[i];759          $$(contextNode).copyDeep(srcNode);760        }761        const hostNode = this.contextNode.parentNode || this.contextNode.ownerElement || this.contextNode.documentElement;762        hostNode.appendChild(contextNode);763        select = select.replace(/^\s*document\(.*?\)/, '.');764      }765    } else if ((/^\s*\$([^/]+)/).test(select)) {766      const srcVariable = select.replace(/^\s*\$([^/]+).*$/, '$1');767      const variable = this.getVariable(srcVariable);768      if (!variable || ['string', 'number', 'boolean'].includes(typeof variable)) {769        return variable;770      } else if (variable instanceof Array && variable.length === 1 && variable[0].nodeType === Node.ATTRIBUTE_NODE) {771        return variable[0].nodeValue;772      } else {773        variableNode = variable;774      }775      const documentNode = (this.contextNode.nodeType === Node.DOCUMENT_NODE) ? this.contextNode : this.contextNode.ownerDocument;776      contextNode = documentNode.createElement('temp');777      for (let i = 0; i < variableNode.childNodes.length; i++) {778        const srcNode = variableNode.childNodes[i];779        $$(contextNode).copyDeep(srcNode);780      }781      const hostNode = this.contextNode.parentNode || this.contextNode.ownerElement || this.contextNode.documentElement;782      hostNode.appendChild(contextNode);783      select = select.replace(/^\s*\$[^/]*/, '.');784    } else {785      contextNode = this.contextNode;786    }787    try {788      const context = this.clone({ contextNode: contextNode, transformNode: transformNode });789      value = $$(context.contextNode).select(select, context, { type: type });790    } finally {791      if (contextNode.nodeName === 'temp') {792        // while (contextNode.firstChild) {793        //   const srcNode = contextNode.firstChild;794        //   srcNode.parentNode.removeChild(srcNode);795        //   contextNode.parentNode.insertBefore(srcNode, contextNode);796        // }797        contextNode.parentNode.removeChild(contextNode);798      }799    }800    return value;801  }802  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -803  /*804   * @method xsltApplyTemplates805   * @instance806   * @implements <xsl:apply-templates>807   * @param {Node} transformNode - The node being evaluated.808   * @param {Node} outputNode - The document to apply the results to.809   */810  async xsltApplyTemplates (811    transformNode,812    outputNode813  ) {814    this.logTransform(transformNode);815    XsltContext.indent++;816    try {817      const mode = $$(transformNode).getAttribute('mode') || undefined;818      const modeTemplateNodes = this.getTemplateNodes(transformNode.ownerDocument, mode);819      this.debug('- ' +820        ((modeTemplateNodes.length === 0) ? 'no' : modeTemplateNodes.length) + ' ' +821        ((mode) ? mode + ' ' : '') +822        'templates to apply');823      if (modeTemplateNodes.length === 0) {824        return;825      }826      const select = $$(transformNode).getAttribute('select');827      const contextNodes = ((select) ? await this.xsltSelect(transformNode, select) : this.contextNode.childNodes); // || [];828      this.debug('- ' +829        ((contextNodes.length === 0) ? 'no' : contextNodes.length) +830        ' context nodes selected against ' + this.getContext());831      if (contextNodes.length === 0) {832        return;833      }834      const sortContext = this.clone({ contextNode: contextNodes[0], transformNode: transformNode, contextPosition: 1, nodeList: contextNodes });835      await sortContext.processChildNodes(transformNode, outputNode, { filter: ['xsl:with-param'], ignoreText: true });836      for (let i = 0; i < sortContext.nodeList.length; i++) {837        const contextNode = sortContext.nodeList[i];838        let processed = false;839        for (let j = 0; j < modeTemplateNodes.length; j++) {840          const modeTemplateNode = modeTemplateNodes[j];841          const context = sortContext.clone({842            contextNode: contextNode,843            contextPosition: i + 1,844            variables: sortContext.variables,845            mode: mode846          });847          if (await context.process(modeTemplateNode, outputNode)) {848            processed = true;849            break;850          }851        }852        if (!processed && contextNode.nodeType === Node.TEXT_NODE) {853          $$(outputNode).copy(contextNode);854        }855      }856      sortContext.sortNodes(transformNode);857    } finally {858      XsltContext.indent--;859    }860  }861  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -862  /*863   * @method xsltAttribute864   * @instance865   * @implements <xsl:attribute>866   * @param {Node} transformNode - The node being evaluated.867   * @param {Node} outputNode - The document to apply the results to.868   */869  async xsltAttribute (870    transformNode,871    outputNode872  ) {873    const nameExpr = $$(transformNode).getAttribute('name');874    const name = this.resolveExpression(transformNode, nameExpr);875    const fragmentNode = transformNode.ownerDocument.createDocumentFragment();876    await this.processChildNodes(transformNode, fragmentNode);877    const value = fragmentNode.textContent;878    outputNode.setAttribute(name, value);879  }880  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -881  /*882   * @method xsltCallTemplate883   * @instance884   * @implements <xsl:call-template>885   * @param {Node} transformNode - The node being evaluated.886   * @param {Node} outputNode - The document to apply the results to.887   */888  async xsltCallTemplate (889    transformNode,890    outputNode891  ) {892    const name = $$(transformNode).getAttribute('name');893    const paramContext = this.clone();894    await paramContext.processChildNodes(transformNode, outputNode, { filter: ['xsl:with-param'], ignoreText: true });895    const templateNode = this.getTemplateNode(transformNode.ownerDocument, name);896    if (templateNode) {897      await paramContext.processChildNodes(templateNode, outputNode);898    }899  }900  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -901  /*902   * @method xsltChoose903   * @instance904   * @implements <xsl:choose> (and <xsl:when> and <xsl:otherwise>)905   * @param {Node} transformNode - The node being evaluated.906   * @param {Node} outputNode - The document to apply the results to.907   */908  async xsltChoose (909    transformNode,910    outputNode911  ) {912    this.logTransform(transformNode);913    XsltContext.indent++;914    try {915      for (let i = 0; i < transformNode.childNodes.length; i++) {916        const childTransformNode = transformNode.childNodes[i];917        if (childTransformNode.nodeType !== Node.ELEMENT_NODE) {918          continue;919        }920        if ($$(childTransformNode).isA('xsl:when')) {921          const test = $$(childTransformNode).getAttribute('test');922          if (test && this.xsltTest(transformNode, test)) {923            this.debug('- selected ' + Utils.identify(childTransformNode) + ' against ' + this.getContext());924            await this.processChildNodes(childTransformNode, outputNode);925            return true;926          }927        } else if ($$(childTransformNode).isA('xsl:otherwise')) {928          this.debug('- selected ' + Utils.identify(childTransformNode) + ' against ' + this.getContext());929          await this.processChildNodes(childTransformNode, outputNode);930          return true;931        }932      }933    } finally {934      XsltContext.indent--;935    }936    return false;937  }938  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -939  /*940   * @method xsltComment941   * @instance942   * @implements <xsl:comment>943   * @param {Node} transformNode - The node being evaluated.944   * @param {Node} outputNode - The document to apply the results to.945   */946  async xsltComment (947    transformNode,948    outputNode949  ) {950    const outputDocument = outputNode.ownerDocument;951    const fragmentNode = transformNode.ownerDocument.createDocumentFragment();952    await this.processChildNodes(transformNode, fragmentNode);953    const commentData = fragmentNode.textContent;954    const newComment = outputDocument.createComment(commentData);955    outputNode.appendChild(newComment);956  }957  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -958  /*959   * @method xsltCopy960   * @instance961   * @implements <xsl:copy>962   * @param {Node} transformNode - The node being evaluated.963   * @param {Node} outputNode - The document to apply the results to.964   */965  async xsltCopy (966    transformNode,967    outputNode968  ) {969    this.logTransform(transformNode);970    XsltContext.indent++;971    try {972      const copyNode = $$(outputNode).copy(this.contextNode);973      if (copyNode) {974        this.debug('- ' + this.getContext() + ' copy success');975        if ([Node.ELEMENT_NODE, Node.DOCUMENT_NODE, Node.DOCUMENT_FRAGMENT_NODE].includes(copyNode.nodeType)) {976          await this.processChildNodes(transformNode, copyNode);977        }978      }979    } finally {980      XsltContext.indent--;981    }982  }983  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -984  /*985   * @method xsltCopyOf986   * @instance987   * @implements <xsl:copy-of>988   * @param {Node} transformNode - The node being evaluated.989   * @param {Node} outputNode - The document to apply the results to.990   */991  async xsltCopyOf (992    transformNode,993    outputNode994  ) {995    const outputDocument = outputNode.ownerDocument;996    const select = $$(transformNode).getAttribute('select');997    if (select) {998      const contextNodes = await this.xsltSelect(transformNode, select);999      if (contextNodes.length > 1) {1000        contextNodes.forEach((contextNode) => {1001          $$(outputNode).copyDeep(contextNode);1002        });1003      } else if (contextNodes.length === 1) {1004        const text = $$(contextNodes[0]).textContent;1005        const newTextNode = $$(outputDocument).createTextNode(text);1006        outputNode.appendChild(newTextNode);1007      }1008    }1009  }1010  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1011  /*1012   * @method xsltDecimalFormat1013   * @instance1014   * @implements <xsl:decimal-format>1015   * @param {Node} transformNode - The node being evaluated.1016   * @param {Node} outputNode - The document to apply the results to.1017   */1018  xsltDecimalFormat (1019    transformNode,1020    outputNode1021  ) {1022    const name = $$(transformNode).getAttribute('name') || '_default';1023    XPathFunctionResolver.decimalFormats[name] = {1024      decimalSeparator: $$(transformNode).getAttribute('decimal-separator') || '.',1025      groupingSeparator: $$(transformNode).getAttribute('grouping-separator') || ',',1026      infinity: $$(transformNode).getAttribute('infinity') || 'Infinity',1027      minusSign: $$(transformNode.getAttribute('minus-sign')) || '-',1028      NaN: $$(transformNode).getAttribute('NaN') || 'NaN',1029      percent: $$(transformNode).getAttribute('percent') || '%',1030      perMille: $$(transformNode).getAttribute('per-mille') || '\u2030',1031      zeroDigit: $$(transformNode).getAttribute('zero-digit') || '0',1032      patternSeparator: $$(transformNode).getAttribute('pattern-separator') || ';'1033    };1034  }1035  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1036  /*1037   * @method xsltElement1038   * @instance1039   * @implements <xsl:element>1040   * @param {Node} transformNode - The node being evaluated.1041   * @param {Node} outputNode - The document to apply the results to.1042   */1043  async xsltElement (1044    transformNode,1045    outputNode1046  ) {1047    const outputDocument = outputNode.ownerDocument;1048    const qNameExpr = $$(transformNode).getAttribute('name');1049    const qName = this.resolveExpression(transformNode, qNameExpr);1050    let namespaceURI = $$(transformNode).getAttribute('namespace');1051    if (!namespaceURI) {1052      namespaceURI = $$(this.contextNode).getNamespaceURI(qName);1053    }1054    const newElement = $$(outputDocument).createElementNS(namespaceURI, qName);1055    outputNode.appendChild(newElement);1056    await this.processChildNodes(transformNode, newElement);1057  }1058  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1059  /*1060   * @method xsltForEach1061   * @instance1062   * @implements <xsl:for-each>1063   * @param {Node} transformNode - The node being evaluated.1064   * @param {Node} outputNode - The document to apply the results to.1065   */1066  async xsltForEach (1067    transformNode,1068    outputNode1069  ) {1070    this.logTransform(transformNode);1071    XsltContext.indent++;1072    try {1073      const select = $$(transformNode).getAttribute('select');1074      if (select) {1075        const contextNodes = await this.xsltSelect(transformNode, select);1076        if (contextNodes.length > 0) {1077          this.debug('- select ' + select + ' against ' + this.getContext());1078          const sortContext = this.clone({ contextNode: contextNodes[0], contextPosition: 1, nodeList: contextNodes });1079          sortContext.sortNodes(transformNode);1080          for (let i = 0; i < sortContext.nodeList.length; i++) {1081            const contextNode = sortContext.nodeList[i];1082            const context = sortContext.clone({1083              contextNode: contextNode,1084              contextPosition: i + 11085            });1086            await context.processChildNodes(transformNode, outputNode);1087          }1088        } else {1089          this.debug('- no nodes to iterate');1090        }1091      }1092    } finally {1093      XsltContext.indent--;1094    }1095  }1096  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1097  /*1098   * @method xsltFunction1099   * @instance1100   * @implements <xsl:function>1101   * @param {Node} transformNode - The node being evaluated.1102   * @param {Node} outputNode - The document to apply the results to.1103   */1104  xsltFunction (1105    transformNode,1106    outputNode1107  ) {1108    // Do nothing - the function resolver will handle this1109  }1110  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1111  /*1112   * @method xsltIf1113   * @instance1114   * @implements <xsl:if>1115   * @param {Node} transformNode - The node being evaluated.1116   * @param {Node} outputNode - The document to apply the results to.1117   */1118  async xsltIf (1119    transformNode,1120    outputNode1121  ) {1122    this.logTransform(transformNode);1123    XsltContext.indent++;1124    try {1125      const test = $$(transformNode).getAttribute('test');1126      if (test && this.xsltTest(transformNode, test)) {1127        this.debug('- test ' + test);1128        await this.processChildNodes(transformNode, outputNode);1129      } else {1130        this.debug('- no match');1131      }1132    } finally {1133      XsltContext.indent--;1134    }1135  }1136  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1137  /*1138   * @method xsltInclude1139   * @instance1140   * @implements <xsl:include>1141   * @param {Node} transformNode - The node being evaluated.1142   */1143  async xsltInclude (1144    transformNode1145  ) {1146    this.logTransform(transformNode);1147    XsltContext.indent++;1148    try {1149      if (!transformNode.hasAttribute('href')) {1150        this.debug('- skipping (no href)');1151        return;1152      }1153      let url = transformNode.getAttribute('href');1154      if ((/^\./).test(url) && this.transformURL) {1155        url = this.transformURL.replace(/[^/]+$/, '') + url.replace(/^\.\//, '');1156      }1157      try {1158        transformNode.removeAttribute('href'); // To prevent any infinite loops1159        const responseXML = await Utils.fetch(url);1160        if (responseXML) {1161          const DOMParser = new XmlDOM.DOMParser();1162          const responseDoc = DOMParser.parseFromString(responseXML);1163          const fragmentTransformNode = transformNode.ownerDocument.createDocumentFragment();1164          const includeTransformNode = $$(fragmentTransformNode).copyDeep(responseDoc.documentElement);1165          if (transformNode.localName === 'include') {1166            while (includeTransformNode.firstChild) {1167              const childIncludeTransformNode = includeTransformNode.firstChild;1168              includeTransformNode.removeChild(childIncludeTransformNode);1169              transformNode.parentNode.insertBefore(childIncludeTransformNode, transformNode);1170            }1171          } else {1172            while (includeTransformNode.firstChild) {1173              const childIncludeTransformNode = includeTransformNode.firstChild;1174              includeTransformNode.removeChild(childIncludeTransformNode);1175              transformNode.parentNode.appendChild(childIncludeTransformNode);1176            }1177          }1178          transformNode.parentNode.removeChild(transformNode);1179          this.debug('Resolved ' + transformNode.localName + ' -> ' + url);1180        }1181      } catch (exception) {}1182    } finally {1183      XsltContext.indent--;1184    }1185  }1186  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1187  /*1188   * @method xsltImport1189   * @instance1190   * @implements <xsl:import>1191   * @param {Node} transformNode - The node being evaluated.1192   */1193  async xsltImport (1194    transformNode1195  ) {1196    // The xsltImport implementation will take care of the differences1197    await this.xsltInclude(transformNode);1198  }1199  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1200  /*1201   * @method xsltOutput1202   * @instance1203   * @implements <xsl:output>1204   * @param {Node} transformNode - The node being evaluated.1205   * @param {Node} outputNode - The document to apply the results to.1206   */1207  xsltOutput (1208    transformNode,1209    outputNode1210  ) {1211    this.logTransform(transformNode);1212    XsltContext.indent++;1213    try {1214      XsltContext.output = {1215        method: transformNode.getAttribute('method'),1216        version: transformNode.getAttribute('version') || '1.0',1217        encoding: transformNode.getAttribute('encoding') || 'UTF-8',1218        omitXmlDeclaration: transformNode.getAttribute('omit-xml-declaration') || 'no',1219        standalone: transformNode.getAttribute('standalone') || 'no',1220        indent: transformNode.getAttribute('indent') || 'no',1221        mediaType: transformNode.getAttribute('media-type') || 'application/xml'1222      };1223    } finally {1224      XsltContext.indent--;1225    }1226  }1227  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1228  /*1229   * @method xsltParam1230   * @instance1231   * @implements <xsl:param>1232   * @param {Node} transformNode - The node being evaluated.1233   * @param {Node} outputNode - The document to apply the results to.1234   * @param {Object} [options={}] -1235   */1236  async xsltParam (1237    transformNode,1238    outputNode,1239    options = {}1240  ) {1241    this.logTransform(transformNode);1242    XsltContext.indent++;1243    try {1244      await this.processVariable(transformNode, { asText: true });1245    } finally {1246      XsltContext.indent--;1247    }1248  }1249  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1250  /*1251   * @method xsltPreserveSpace1252   * @instance1253   * @implements <xsl:preserve-space>1254   * @param {Node} transformNode - The node being evaluated.1255   * @param {Node} outputNode - The document to apply the results to.1256   */1257  async xsltPreserveSpace (1258    transformNode,1259    outputNode1260  ) {1261    let elements = $$(transformNode).getAttribute('elements');1262    elements = elements.replace(/(^\s+|\s(?:\s+)|\s+$)/, '').split(' ');1263    elements.forEach((elementName) => {1264      const namespaceURI = (/:/).test(elementName) ? transformNode.lookupNamespaceURI(elementName.replace(/:.*/, '')) : null;1265      const localName = elementName.replace(/^.*:/, '');1266      const fullName = ((namespaceURI) ? '{' + namespaceURI + '}' : '') + localName;1267      this.cfg.preserveSpaceList[fullName] = elementName;1268    });1269  }1270  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1271  /*1272   * @method xsltProcessingInstruction1273   * @instance1274   * @implements <xsl:processing-instruction>1275   * @param {Node} transformNode - The node being evaluated.1276   * @param {Node} outputNode - The document to apply the results to.1277   */1278  async xsltProcessingInstruction (1279    transformNode,1280    outputNode1281  ) {1282    const outputDocument = outputNode.ownerDocument;1283    const nameExpr = $$(transformNode).getAttribute('name');1284    const target = this.resolveExpression(transformNode, nameExpr);1285    const fragmentNode = transformNode.ownerDocument.createDocumentFragment();1286    await this.processChildNodes(transformNode, fragmentNode);1287    const data = fragmentNode.textContent;1288    const newPI = $$(outputDocument).createProcessingInstruction(target, data);1289    outputNode.appendChild(newPI);1290  }1291  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1292  /*1293   * Does nothing as sorting is handled earlier1294   * @method xsltSort1295   * @instance1296   * @implements <xsl:sort>1297   * @param {Node} transformNode - The node being evaluated.1298   * @param {Node} outputNode - The document to apply the results to.1299   */1300  xsltSort (1301    transformNode,1302    outputNode1303  ) {1304  }1305  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1306  /*1307   * @method xsltStripSpace1308   * @instance1309   * @implements <xsl:strip-space>1310   * @param {Node} transformNode - The node being evaluated.1311   * @param {Node} outputNode - The document to apply the results to.1312   */1313  xsltStripSpace (1314    transformNode,1315    outputNode1316  ) {1317    let elements = $$(transformNode).getAttribute('elements');1318    elements = elements.replace(/(^\s+|\s(?:\s+)|\s+$)/, '').split(' ');1319    elements.forEach((elementName) => {1320      const namespaceURI = (/:/).test(elementName) ? transformNode.lookupNamespaceURI(elementName.replace(/:.*/, '')) : null;1321      const localName = elementName.replace(/^.*:/, '');1322      const fullName = ((namespaceURI) ? '{' + namespaceURI + '}' : '') + localName;1323      this.cfg.stripSpaceList[fullName] = elementName;1324    });1325  }1326  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1327  /*1328   * @method xsltStylesheet1329   * @instance1330   * @implements <xsl:stylesheet>1331   * @param {Node} transformNode - The node being evaluated.1332   * @param {Node} outputNode - The document to apply the results to.1333   */1334  async xsltStylesheet (1335    transformNode,1336    outputNode1337  ) {1338    await this.xsltTransform(transformNode, outputNode);1339  }1340  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1341  /*1342   * @method xsltTransform1343   * @instance1344   * @implements <xsl:transform>1345   * @param {Node} transformNode - The node being evaluated.1346   * @param {Node} outputNode - The document to apply the results to.1347   */1348  async xsltTransform (1349    transformNode,1350    outputNode1351  ) {1352    this.logTransform(transformNode);1353    XsltContext.indent++;1354    try {1355      // Resolve all the imports and includes1356      await this.processIncludes(transformNode);1357      this.debug('- all includes/imports processed');1358      let rootTemplate = false;1359      for (let i = 0; i < transformNode.childNodes.length; i++) {1360        const childTransformNode = transformNode.childNodes[i];1361        if ($$(childTransformNode).isA('xsl:output')) {1362          this.xsltOutput(childTransformNode, outputNode);1363        } else if ($$(childTransformNode).isA('xsl:strip-space')) {1364          this.xsltStripSpace(childTransformNode, outputNode);1365        } else if ($$(childTransformNode).isA('xsl:preserve-space')) {1366          this.xsltPreserveSpace(childTransformNode, outputNode);1367        } else if ($$(childTransformNode).isA('xsl:variable')) {1368          await this.xsltVariable(childTransformNode, outputNode);1369        } else if ($$(childTransformNode).isA('xsl:template') && childTransformNode.getAttribute('match') === '/') {1370          rootTemplate = true;1371          const context = this.clone({ contextNode: this.contextNode.ownerDocument });1372          await context.processChildNodes(childTransformNode, outputNode);1373          return true;1374        }1375      }1376      if (!rootTemplate) {1377        await this.processChildNodes(transformNode, outputNode, { ignoreText: true });1378      }1379    } finally {1380      XsltContext.indent--;1381    }1382  }1383  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1384  /*1385   * @method xsltTemplate1386   * @instance1387   * @implements <xsl:template>1388   * @param {Node} transformNode - The node being evaluated.1389   * @param {Node} outputNode - The document to apply the results to.1390   */1391  async xsltTemplate (1392    transformNode,1393    outputNode1394  ) {1395    this.logTransform(transformNode);1396    XsltContext.indent++;1397    try {1398      const match = $$(transformNode).getAttribute('match');1399      const mode = $$(transformNode).getAttribute('mode') || null;1400      if (match && ((mode && mode === this.mode) || (!mode && !this.mode))) {1401        if (this.xsltMatch(transformNode, match)) {1402          this.debug('- matched against ' + this.getContext());1403          await this.processChildNodes(transformNode, outputNode);1404          return true;1405        } else {1406          this.debug('- skipping against ' + this.getContext());1407        }1408      }1409    } finally {1410      XsltContext.indent--;1411    }1412    return false;1413  }1414  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1415  /*1416   * @method xsltText1417   * @instance1418   * @implements <xsl:text>1419   * @param {Node} transformNode - The node being evaluated.1420   * @param {Node} outputNode - The document to apply the results to.1421   */1422  xsltText (1423    transformNode,1424    outputNode1425  ) {1426    let disableOutputEscaping = false;1427    if (transformNode.hasAttribute('disable-output-escaping') && transformNode.getAttribute('disable-output-escaping').toLowerCase() === 'yes') {1428      disableOutputEscaping = true;1429    }1430    const outputDocument = outputNode.ownerDocument;1431    let text = $$(transformNode).textContent;1432    if (disableOutputEscaping) {1433      text = text.replace(/([<>'"&])/g, '[[$1]]');1434    }1435    const newTextNode = $$(outputDocument).createTextNode(text);1436    outputNode.appendChild(newTextNode);1437  }1438  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1439  /*1440   * @method xsltValueOf1441   * @instance1442   * @implements <xsl:value-of>1443   * @param {Node} transformNode - The node being evaluated.1444   * @param {Node} outputNode - The document to apply the results to.1445   */1446  async xsltValueOf (1447    transformNode,1448    outputNode1449  ) {1450    let disableOutputEscaping = false;1451    if (transformNode.hasAttribute('disable-output-escaping') && transformNode.getAttribute('disable-output-escaping').toLowerCase() === 'yes') {1452      disableOutputEscaping = true;1453    }1454    const outputDocument = outputNode.ownerDocument;1455    const select = $$(transformNode).getAttribute('select');1456    if (select) {1457      let value = await this.xsltSelect(transformNode, select, XPath.XPathResult.STRING_TYPE);1458      if (value) {1459        value = this.processWhitespace(value, this.contextNode);1460        this.debug('- select ' + select + ' = ' + value.toString());1461        if (disableOutputEscaping) {1462          value = value.replace(/([<>'"&])/g, '[[$1]]');1463        }1464        const newTextNode = $$(outputDocument).createTextNode(value);1465        outputNode.appendChild(newTextNode);1466      } else {1467        this.debug('- no value');1468      }1469    }1470  }1471  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1472  /*1473   * @method xsltVariable1474   * @instance1475   * @implements <xsl:variable>1476   * @param {Node} transformNode - The node being evaluated.1477   * @param {Node} outputNode - The document to apply the results to.1478   */1479  async xsltVariable (1480    transformNode,1481    outputNode1482  ) {1483    this.logTransform(transformNode);1484    XsltContext.indent++;1485    try {1486      const variableName = transformNode.getAttribute('name');1487      await this.processVariable(transformNode, { override: true /*, asText: true */ });1488      this.debug('- variable ' + variableName + ' = "' + this.getVariable(variableName).toString() + '"');1489    } finally {1490      XsltContext.indent--;1491    }1492  }1493  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -1494  /*1495   * @method xsltWithParam1496   * @instance1497   * @implements <xsl:with-param>1498   * @param {Node} transformNode - The node being evaluated.1499   * @param {Node} outputNode - The document to apply the results to.1500   */1501  async xsltWithParam (1502    transformNode,1503    outputNode1504  ) {1505    await this.processVariable(transformNode, { override: true, asText: true });1506  }1507};1508// ----------------------------------------------------------------------------1509// Static properties1510// ----------------------------------------------------------------------------1511XsltContext.indent = 0;1512XsltContext.fetchCache = {};1513// ----------------------------------------------------------------------------1514// Exports1515// ----------------------------------------------------------------------------1516exports.XsltContext = XsltContext;...

Full Screen

Full Screen

FABRIC.SceneGraph.Kinematics.js

Source:FABRIC.SceneGraph.Kinematics.js Github

copy

Full Screen

1//2// Copyright 2010-2011 Fabric Technologies Inc. All rights reserved.3//4FABRIC.SceneGraph.registerNodeType('Transform', {5  briefDesc: 'The Transform node implements a global or hierarchical transform.',6  detailedDesc: 'The Transform node uses a redraw eventhandler to draw an OpenGL projection. The node can be used in '+7                'a hierarchical mode, in which is projects its own projection into another Transform node\'s projection. '+8                'This allows to compute hierarchies in 3D.',9  parentNodeDesc: 'SceneGraphNode',10  optionsDesc: {11    hierarchical: 'Flag determining wether this Transform node should calculate a globalXfo based on a parents globalXfo',12    parentTransformNode: 'If the TransformNode is hierarchical, this option can optionally provide a parent transform node to immediately assign',13    globalXfo: 'Optional: Specify the intial globalXfo for this transform.',14    localXfo: 'Optional: Specify the intial localXfo for this transform.'15  },16  factoryFn: function(options, scene) {17    scene.assignDefaults(options, {18        hierarchical: false,19        parentTransformNode: undefined,20        globalXfo: undefined,21        localXfo: undefined22      });23    var transformNode = scene.constructNode('SceneGraphNode', options),24      dgnode = transformNode.constructDGNode('DGNode'),25      textureNode = undefined,26      parentTransformNode,27      children = [];28    dgnode.addMember('globalXfo', 'Xfo', options.globalXfo);29    transformNode.addMemberInterface(dgnode, 'globalXfo');30    if (options.hierarchical) {31      dgnode.addMember('localXfo', 'Xfo', options.localXfo);32      dgnode.bindings.append(scene.constructOperator( {33          operatorName: 'calcGlobalXfo',34          srcFile: 'FABRIC_ROOT/SceneGraph/KL/calcGlobalXfo.kl',35          parameterLayout: [36            'self.localXfo',37            'parent.globalXfo',38            'self.globalXfo'39          ],40          entryFunctionName: 'calcGlobalXfo'41        }));42      transformNode.addMemberInterface(dgnode, 'localXfo', true, true);43      // use a custom getter44      transformNode.pub.setGlobalXfo = function(val) {45        if (!val.getType || val.getType() !== 'FABRIC.RT.Xfo') {46          throw ('Incorrect type assignment. Must assign a FABRIC.RT.Xfo');47        }48        if (parentTransformNode) {49          var parentXfo = parentTransformNode.getGlobalXfo();50          parentXfo.invertInPlace();51          val.preMultiplyInPlace(parentXfo);52          dgnode.setData('localXfo', val);53        }54        else {55          dgnode.setData('globalXfo', val);56        }57      };58      transformNode.pub.getParentNode = function() {59        return scene.getPublicInterface(parentTransformNode);60      };61      transformNode.pub.setParentNode = function(node, reciprocate) {62        if (!node.isTypeOf('Transform')) {63          throw ('Incorrect type assignment. Must assign a Transform');64        }65        parentTransformNode = scene.getPrivateInterface(node);66        dgnode.setDependency(parentTransformNode.getDGNode(), 'parent');67        if (reciprocate !== false && node.addChild) {68          node.addChild(this, false);69        }70      };71      transformNode.pub.addChild = function(node, reciprocate) {72        children.push(node);73        if (reciprocate !== false) {74          node.setParentNode(this, false);75        }76      };77      transformNode.pub.getChildren = function() {78        return children;79      };80      if (options.parentTransformNode) {81        transformNode.pub.setParentNode(options.parentTransformNode);82      }83    }else {84      transformNode.pub.setGlobalXfo = function(val) {85        if(val.constructor.toString().indexOf("Array") != -1)86        {87          dgnode.setCount(val.length);88          dgnode.setBulkData({ globalXfo: val});89        }90        else91        {92          if (!val.getType || val.getType() !== 'FABRIC.RT.Xfo') {93            throw ('Incorrect type assignment. Must assign a FABRIC.RT.Xfo');94          }95          dgnode.setData('globalXfo', 0, val);96        }97      };98    }99    100    transformNode.setupInstanceDrawing = function(dynamic) {101      if(textureNode != undefined)102        return true;103      if(dgnode.getCount() <= 1)104        return false;105      106      // create the operator to convert the matrices into a texture107      dgnode.addMember('textureMatrix', 'Mat44');108      dgnode.bindings.append(scene.constructOperator( {109          operatorName: 'calcGlobalMatrix',110          srcFile: 'FABRIC_ROOT/SceneGraph/KL/calcGlobalXfo.kl',111          parameterLayout: [112            'self.globalXfo',113            'self.textureMatrix'114          ],115          entryFunctionName: 'calcGlobalMatrix'116        }));117      textureNode = scene.constructNode('TransformTexture', {transformNode: transformNode.pub, dynamic: dynamic});118      return true;  119    }120    121    transformNode.pub.getTransformTexture = function(dynamic) {122      transformNode.setupInstanceDrawing(dynamic);123      return textureNode.pub;124    }125    return transformNode;126  }});127FABRIC.SceneGraph.registerNodeType('TransformTexture', {128  briefDesc: 'The TransformTexture node is an Image node which can be used for storing matrices into a texture buffer.',129  detailedDesc: 'The TransformTexture node is an Image node which can be used for storing matrices into a texture buffer. This is used for efficient instance rendering.',130  parentNodeDesc: 'Texture',131  optionsDesc: {132    transformNode: 'A sliced transform node storing all of the transform to store.',133    dynamic: 'If set to true, the texture will be reloaded every frame.'134  },135  factoryFn: function(options, scene) {136    scene.assignDefaults(options, {137      transformNode: undefined,138      dynamic: undefined139    });140    141    if(!options.transformNode) {142      throw('You need to specify a transformNode for this constructor!');143    }144    if(!options.transformNode.isTypeOf('Transform')) {145      throw('The specified transformNode is not of type \'Transform\'.');146    }147    var transformdgnode = scene.getPrivateInterface(options.transformNode).getDGNode();148    var textureNode = scene.constructNode('Texture', options);149    150    var redrawEventHandler = textureNode.constructEventHandlerNode('Redraw');151    textureNode.getRedrawEventHandler = function() { return redrawEventHandler; }152    153    var tex = FABRIC.RT.oglMatrixBuffer2D();154    if(!options.dynamic)155      tex.forceRefresh = false;156    redrawEventHandler.addMember('oglTexture2D', 'OGLTexture2D', tex);157    redrawEventHandler.setScope('transform', transformdgnode);158    redrawEventHandler.preDescendBindings.append(scene.constructOperator({159      operatorName: 'setNumberOfMatrices',160      srcFile: 'FABRIC_ROOT/SceneGraph/KL/loadTexture.kl',161      entryFunctionName: 'setNumberOfMatrices',162      parameterLayout: [163        'transform.textureMatrix<>',164        'shader.shaderProgram'165      ]166    }));167    redrawEventHandler.preDescendBindings.append(scene.constructOperator({168      operatorName: 'bindTextureMatrix',169      srcFile: 'FABRIC_ROOT/SceneGraph/KL/loadTexture.kl',170      entryFunctionName: 'bindTextureMatrix',171      parameterLayout: [172        'self.oglTexture2D',173        'textureStub.textureUnit',174        'transform.textureMatrix<>'175      ]176    }));177    178    return textureNode;179  }});180FABRIC.SceneGraph.registerNodeType('AimTransform', {181  briefDesc: 'The AimTransform node implements a global lookat transform.',182  detailedDesc: 'The AimTransform uses the Transform node to implement a lookat transform, using a '+183                'root position as well as a target position. This node is used for the TargetCamera node.',184  parentNodeDesc: 'Transform',185  optionsDesc: {186    target: 'The target position for the initial direction of the Transform'187  },188  factoryFn: function(options, scene) {189    scene.assignDefaults(options, {190        target: FABRIC.RT.vec3(0, 0, 0)191      });192    193    if(options.position && options.target){194      options.globalXfo = FABRIC.RT.xfo({ tr: options.position });195      196      var dirVec = options.position.subtract(options.target);197      var vec1 = options.globalXfo.ori.getZaxis();198      var vec2 = dirVec.unit();199      options.globalXfo.ori = FABRIC.RT.Quat.makeFrom2Vectors(FABRIC.RT.vec3(0, 0, 1) , vec2, true);200      vec1 = options.globalXfo.ori.getYaxis();201      vec2 = dirVec.cross(FABRIC.RT.vec3(0, 1, 0) ).cross(dirVec).unit();202      options.globalXfo.ori.postMultiplyInPlace( FABRIC.RT.Quat.makeFrom2Vectors(vec1, vec2, true));203      204/*205      var zaxis = options.position.subtract(options.target).unit();206      var yaxis = zaxis.cross(FABRIC.RT.vec3(0, 1, 0) ).cross(zaxis).unit();207      var xaxis = yaxis.cross(zaxis).unit();208      options.globalXfo = FABRIC.RT.xfo({ tr: options.position });209      options.globalXfo.ori.setFromMat33(FABRIC.RT.mat33(xaxis, yaxis, zaxis));210*/  }211    var aimTransformNode = scene.constructNode('Transform', options);212    var dgnode = aimTransformNode.getDGNode();213    dgnode.addMember('target', 'Vec3', options.target);214    dgnode.bindings.append(scene.constructOperator({215      operatorName: 'aimTransform',216      srcFile: 'FABRIC_ROOT/SceneGraph/KL/aimTransform.kl',217      entryFunctionName: 'aimTransform',218      parameterLayout: [219        'self.globalXfo',220        'self.target'221      ]222    }));223    aimTransformNode.addMemberInterface(dgnode, 'target', true);224    return aimTransformNode;...

Full Screen

Full Screen

cson_parse.js

Source:cson_parse.js Github

copy

Full Screen

...85      throw new SyntaxError(86        syntaxErrorMessage(node, 'One top level value expected')87      );88    }89    return transformNode(expressions[0]);90  },91  Value: function Value(node, transformNode) {92    return transformNode(node.base);93  },94  Bool: function Bool(node) {95    return node.val === 'true';96  },97  BooleanLiteral: function BooleanLiteral(node) {98    return node.value === 'true';99  },100  Null: function Null() {101    return null;102  },103  NullLiteral: function NullLiteral() {104    return null;105  },106  Literal: function Literal(node) {107    var value = node.value;108    try {109      switch (value.charAt(0)) {110        case "'":111        case '"':112          return parseStringLiteral(value);113        case '/':114          return parseRegExpLiteral(value);115        default:116          return JSON.parse(value);117      }118    } catch (error) {119      throw new SyntaxError(syntaxErrorMessage(node, error.message));120    }121  },122  NumberLiteral: function NumberLiteral(node) {123    return Number(node.value);124  },125  StringLiteral: function StringLiteral(node) {126    return parseStringLiteral(node.value);127  },128  RegexLiteral: function RegexLiteral(node) {129    return parseRegExpLiteral(node.value);130  },131  Arr: function Arr(node, transformNode) {132    return _.map(node, transformNode);133  },134  Obj: function Obj(node, transformNode, reviver) {135    return _.reduce(node,function(outObject, property){136      var variable = property.variable;137      var value = property.value;138      if (!variable) {139        return outObject;140      }141      var keyName = transformKey(variable);142      value = transformNode(value);143      outObject[keyName] = reviver.call(outObject, keyName, value);144      return outObject;145    }, {});146  },147  Op: function Op(node, transformNode) {148    if (node.second != null) {149      var left = transformNode(node.first);150      var right = transformNode(node.second);151      switch (node.operator) {152        case '-':153          return left - right;154        case '+':155          return left + right;156        case '*':157          return left * right;158        case '/':159          return left / right;160        case '%':161          return left % right;162        case '&':163          return left & right;164        case '|':165          return left | right;166        case '^':167          return left ^ right;168        case '<<':169          return left << right;170        case '>>>':171          return left >>> right;172        case '>>':173          return left >> right;174        default:175          throw new SyntaxError(176            syntaxErrorMessage(node, "Unknown binary operator " + node.operator)177          );178      }179    } else {180      switch (node.operator) {181        case '-':182          return -transformNode(node.first);183        case '~':184          return ~transformNode(node.first);185        default:186          throw new SyntaxError(187            syntaxErrorMessage(node, "Unknown unary operator " + node.operator)188          );189      }190    }191  },192  Parens: function Parens(node, transformNode) {193    var expressions = node.body.expressions;194    if (!expressions || expressions.length !== 1) {195      throw new SyntaxError(196        syntaxErrorMessage(node, 'Parenthesis may only contain one expression')197      );198    }199    return transformNode(expressions[0]);200  }201};202function parse(source, reviver) {203  if (reviver == null) {204    reviver = defaultReviver;205  }206  function transformNode(csNode) {207    var type = nodeTypeString(csNode);208    var transform = nodeTransforms[type];209    if (!transform) {210      throw new SyntaxError(syntaxErrorMessage(csNode, "Unexpected " + type));211    }212    return transform(csNode, transformNode, reviver);213  }214  if (typeof reviver !== 'function') {215    throw new TypeError('reviver has to be a function');216  }217  var coffeeAst = nodes(source.toString('utf8'));218  var parsed = transformNode(coffeeAst);219  if (reviver === defaultReviver) {220    return parsed;221  }222  var contextObj = {};223  contextObj[''] = parsed;224  return reviver.call(contextObj, '', parsed);225}...

Full Screen

Full Screen

cson-safe.js

Source:cson-safe.js Github

copy

Full Screen

...51        var body;52        body = node.body;53        if (!body || !body.statements || body.statements.length !== 1)54          throw new SyntaxError(syntaxErrorMessage(node, 'One top level value expected'));55        return transformNode(body.statements[0]);56      }57    ],58    [59      CS.ObjectInitialiser,60      function (node) {61        return node.members.reduce(function (outObject, param$) {62          var cache$, expression, key, keyName, value;63          {64            cache$ = param$;65            key = cache$.key;66            expression = cache$.expression;67          }68          keyName = transformKey(key);69          value = transformNode(expression);70          outObject[keyName] = value;71          return outObject;72        }, {});73      }74    ],75    [76      CS.ArrayInitialiser,77      function (node) {78        return node.members.map(transformNode);79      }80    ],81    [82      CS.Null,83      function () {84        return null;85      }86    ],87    [88      CS.UnaryNegateOp,89      function (node) {90        return -transformNode(node.expression);91      }92    ],93    [94      CS.MultiplyOp,95      function (node) {96        return transformNode(node.left) * transformNode(node.right);97      }98    ],99    [100      CS.PlusOp,101      function (node) {102        return transformNode(node.left) + transformNode(node.right);103      }104    ],105    [106      CS.DivideOp,107      function (node) {108        return transformNode(node.left) / transformNode(node.right);109      }110    ],111    [112      CS.SubtractOp,113      function (node) {114        return transformNode(node.left) - transformNode(node.right);115      }116    ],117    [118      CS.RemOp,119      function (node) {120        return transformNode(node.left) % transformNode(node.right);121      }122    ],123    [124      CS.BitAndOp,125      function (node) {126        return transformNode(node.left) & transformNode(node.right);127      }128    ],129    [130      CS.BitOrOp,131      function (node) {132        return transformNode(node.left) | transformNode(node.right);133      }134    ],135    [136      CS.BitXorOp,137      function (node) {138        return transformNode(node.left) ^ transformNode(node.right);139      }140    ],141    [142      CS.BitNotOp,143      function (node) {144        return ~transformNode(node.expression);145      }146    ],147    [148      CS.LeftShiftOp,149      function (node) {150        return transformNode(node.left) << transformNode(node.right);151      }152    ],153    [154      CS.SignedRightShiftOp,155      function (node) {156        return transformNode(node.left) >> transformNode(node.right);157      }158    ],159    [160      CS.UnsignedRightShiftOp,161      function (node) {162        return transformNode(node.left) >>> transformNode(node.right);163      }164    ]165  ];166  LiteralTypes = [167    CS.Bool,168    CS.Float,169    CS.Int,170    CS.String171  ];172  LiteralTypes.forEach(function (LiteralType) {173    return nodeTransforms.unshift([174      LiteralType,175      function (param$) {176        var data;177        data = param$.data;178        return data;179      }180    ]);181  });182  isLiteral = function (csNode) {183    return LiteralTypes.some(function (LiteralType) {184      return csNode instanceof LiteralType;185    });186  };187  transformKey = function (csNode) {188    if (!(csNode instanceof CS.Identifier || isLiteral(csNode)))189      throw new SyntaxError(syntaxErrorMessage(csNode, '' + nodeTypeString(csNode) + ' used as key'));190    return csNode.data;191  };192  transformNode = function (csNode) {193    var transform;194    transform = find(nodeTransforms, function (param$) {195      var NodeType;196      NodeType = param$[0];197      return csNode instanceof NodeType;198    });199    if (!transform)200      throw new SyntaxError(syntaxErrorMessage(csNode, 'Unexpected ' + nodeTypeString(csNode)));201    return transform[1](csNode);202  };203  stringify = function (obj, visitor, indent) {204    return JSON.stringify(obj, visitor, indent);205  };206  parse = function (source, reviver) {207    var coffeeAst;208    if (reviver)209      throw new Error('The reviver parameter is not implemented yet');210    coffeeAst = csr.parse(source.toString(), {211      bare: true,212      raw: true213    });214    return transformNode(coffeeAst);215  };216  module.exports = CSON = {217    stringify: stringify,218    parse: parse219  };...

Full Screen

Full Screen

graphic.js

Source:graphic.js Github

copy

Full Screen

1function drawBackground() {2  var x = arguments[0]||0,3    y = arguments[1]||0,4    w = arguments[2]||COLS*RECT_SIZE,5    h = arguments[3]||ROWS*RECT_SIZE;6  // background7  context.fillStyle = '#ccc';8  context.fillRect(x, y, w, h);9  // // lines10  // context.beginPath();11  // for (var i=1; i<COLS; ++i) {12  //   context.moveTo(i*RECT_SIZE, 0);13  //   context.lineTo(i*RECT_SIZE, ROWS*RECT_SIZE);14  // }15  // for (var i=1; i<ROWS; ++i) {16  //   context.moveTo(0, i*RECT_SIZE);17  //   context.lineTo(COLS*RECT_SIZE, i*RECT_SIZE);18  // }19  // context.lineWidth=1;20  // context.strokeStyle='grey';21  // context.stroke();22}23function drawOne(x, y, type) {24  if (type==6) { // ○25    context.fillStyle = 'black';26    context.beginPath();27    context.arc(x+RECT_SIZE/2, y+RECT_SIZE/2, RECT_SIZE/2-2,28      0, Math.PI*2, true);29    context.closePath();30    context.fill();31    return;32  }33  switch (Math.floor(type)) {34    case 0:35      context.fillStyle = 'yellow';36      break;37    case 1:38      context.fillStyle = 'blue';39      break;40    case 2:41      context.fillStyle = 'red';42      break;43    case 3:44      context.fillStyle = 'brown';45      break;46    case 4:47      context.fillStyle = 'green';48      break;49    case 5:50      context.fillStyle = 'purple';51      break;52    default:53      context.fillStyle = 'white';54  }55  switch (Math.floor(type*10)%10) {56    case 0:57      context.fillRect(x+2, y+2, RECT_SIZE-4, RECT_SIZE-4);58      break;59    case 1: // |60      context.fillRect(x+RECT_SIZE/4, y+2, RECT_SIZE/2, RECT_SIZE-4);61      break;62    case 2: // -63      context.fillRect(x+2, y+RECT_SIZE/4, RECT_SIZE-4, RECT_SIZE/2);64      break;65    case 3: // ◇66      context.beginPath();67      context.moveTo(x+RECT_SIZE/2, y+2);68      context.lineTo(x+RECT_SIZE-2, y+RECT_SIZE/2);69      context.lineTo(x+RECT_SIZE/2, y+RECT_SIZE-2);70      context.lineTo(x+2, y+RECT_SIZE/2);71      context.lineTo(x+RECT_SIZE/2, y+2);72      context.closePath();73      context.fill();74      break;75    default:76      context.fillRect(x+2, y+2, RECT_SIZE-4, RECT_SIZE-4);77  }78}79function drawMap() {80  for (var row=0; row<ROWS; ++row) {81    for (var col=0; col<COLS; ++col) {82      drawOne(col*RECT_SIZE, row*RECT_SIZE, map[col][row]);83    }84  }85}86function animationSwap(col, row, direction, onFinish) {87  var frontX = col*RECT_SIZE,88    frontY = row*RECT_SIZE,89    backX = col*RECT_SIZE,90    backY = row*RECT_SIZE,91    frontOne = map[col][row],92    backOne,93    movementX = 0,94    movementY = 0,95    backgroundX = frontX,96    backgroundY = frontY,97    backgroundW = RECT_SIZE,98    backgroundH = RECT_SIZE;99  switch (direction) {100    case 'up':101      backOne = map[col][row-1];102      backY -= RECT_SIZE;103      movementY = -RECT_SIZE;104      backgroundY -= RECT_SIZE;105      backgroundH += RECT_SIZE;106      break;107    case 'down':108      backOne = map[col][row+1];109      backY += RECT_SIZE;110      movementY = RECT_SIZE;111      backgroundH += RECT_SIZE;112      break;113    case 'left':114      backOne = map[col-1][row];115      backX -= RECT_SIZE;116      movementX = -RECT_SIZE;117      backgroundX -= RECT_SIZE;118      backgroundW += RECT_SIZE;119      break;120    case 'right':121      backOne = map[col+1][row];122      backX += RECT_SIZE;123      movementX = RECT_SIZE;124      backgroundW += RECT_SIZE;125      break;126  }127  var startTime = null;128  var startFrontX = frontX,129    startFrontY = frontY,130    startBackX = backX,131    startBackY = backY;132  var ani = function(time) {133    if (null === startTime) {134      startTime = time;135    }136    drawBackground(backgroundX, backgroundY, backgroundW, backgroundH);137    frontX = startFrontX + movementX * (time - startTime) / (ANIMATION_SEC * 1000);138    frontY = startFrontY + movementY * (time - startTime) / (ANIMATION_SEC * 1000);139    backX = startBackX - movementX * (time - startTime) / (ANIMATION_SEC * 1000);140    backY = startBackY - movementY * (time - startTime) / (ANIMATION_SEC * 1000);141    drawOne(backX, backY, backOne);142    drawOne(frontX, frontY, frontOne);143    if (time - startTime < ANIMATION_SEC * 1000) {144      requestAnimationFrame(ani);145    }146    else {147      onFinish();148    }149  };150  var requestAnimationFrame = window.requestAnimationFrame ||151    window.webkitRequestAnimationFrame ||152    window.mozRequestAnimationFrame ||153    window.msRequestAnimationFrame ||154    window.oRequestAnimationFrame;155  requestAnimationFrame(ani);156}157function animationEliminate(results, onFinish) {158  var result, node, cur;159  for (var posResult in results) {160    result = results[posResult];161    if (result.transformNode) {162      cur = map[result.transformNode.col][result.transformNode.row];163    }164    for (var posNode in result.nodes) {165      node = result.nodes[posNode];166      drawBackground(node.col*RECT_SIZE, node.row*RECT_SIZE,167        RECT_SIZE, RECT_SIZE);168      map[node.col][node.row] = -1;169    }170    if (result.transformNode) {171      switch (result.transformType) {172        case '5':173          map[result.transformNode.col][result.transformNode.row] = 6;174          break;175        case 'T':176          map[result.transformNode.col][result.transformNode.row] = cur+0.3;177          break;178        case '4':179          if (result.vertical) {180            map[result.transformNode.col][result.transformNode.row] = cur+0.2;181          }182          else {183            map[result.transformNode.col][result.transformNode.row] = cur+0.1;184          }185          break;186      }187      drawOne(result.transformNode.col*RECT_SIZE,188        result.transformNode.row*RECT_SIZE,189        map[result.transformNode.col][result.transformNode.row]);190    }191  }192  onFinish();...

Full Screen

Full Screen

index.js

Source:index.js Github

copy

Full Screen

1"use strict";2var parse = require("falafel-harmony");3var SourceNode = require("source-map").SourceNode;4function Transform() {5  this.parserSettings = { loc: true };6}7Transform.prototype.traverseNodeList = function(nodeList, callback) {8  var transform = this;9  nodeList.forEach(function(node) {10    node.moduleNames.forEach(function(moduleName) {11      callback.call(transform, node, moduleName);12    });13  });14};15Transform.prototype.patchNode = function(node, chunks) {16  var update = node.update;17  node.update = function(newContent) {18    var line = this.loc.start.line;19    var column = this.loc.start.column;20    chunks[node.range[0]] = new SourceNode(line, column, "in.js", [newContent]);21    for (var i = node.range[0] + 1; i < node.range[1]; i++) {22      chunks[i] = "";23    }24    // Transparently send back the original.25    return update.apply(this, arguments);26  };27  return node;28};29Transform.prototype.deconstruct = function(source) {30  var moduleDescriptor = {};31  var transform = this;32  var imports = [];33  var exports = {34    default: [],35    named: []36  };37  var lastNode;38  var chunks = source.split("");39  var ast = parse(source, this.parserSettings, function(node) {40    node = transform.patchNode(node, chunks);41    var transformNode;42    lastNode = node;43    // Identify all top level dependency nodes.44    transformNode = transform.import.identify(node);45    if (transformNode) {46      imports.push(transformNode);47    }48    // Find all default exports.49    transformNode = transform.exports.identify(node);50    if (transformNode) {51      exports.default.push(transformNode);52    }53    // Find all single exports.54    transformNode = transform.export.identify(node);55    if (transformNode) {56      exports.named.push(transformNode);57    }58  });59  // The root node, by default, is the program node.60  moduleDescriptor.rootNode = lastNode;61  // Assign chunks.62  moduleDescriptor.chunks = chunks;63  moduleDescriptor.originalSource = source;64  // Iterate over the dependency nodes and extract the valid65  // meta-information.66  moduleDescriptor.imports = imports.map(function(node) {67    // Decorate the import node.68    node.moduleNames = [].concat(transform.import.extract(node));69    return node;70  });71  moduleDescriptor.exports = exports.default.map(function(node) {72    node.moduleNames = [].concat(transform.exports.extract(node));73    return node;74  });75  moduleDescriptor.namedExports = exports.named.map(function(node) {76    node.moduleNames = [].concat(transform.export.extract(node));77    return node;78  });79  // Attach the AST for sharing.80  moduleDescriptor.ast = ast;81  return moduleDescriptor;82};83Transform.prototype.reconstruct = function(moduleDescriptor) {84  this.traverseNodeList(moduleDescriptor.imports, function(node, moduleName) {85    this.import.write(node, moduleName);86  });87  this.traverseNodeList(moduleDescriptor.exports, function(node, moduleName) {88    this.exports.write(node, moduleName);89  });90  this.traverseNodeList(moduleDescriptor.namedExports, function(node, assignment) {91    this.export.write(node, assignment.property, assignment.value);92  });93  if (this.import.beforeComplete) {94    this.import.beforeComplete.call(this, moduleDescriptor);95  }96  // Generate the parent Source Map.97  var root = new SourceNode(null, null, null, moduleDescriptor.chunks);98  // Add the content.99  root.setSourceContent("in.js", moduleDescriptor.originalSource);100  var sm = root.toStringWithSourceMap({ file: "out.js" });101  var sourceMap = moduleDescriptor.sourceMap = sm.map.toString();102  // Remove the excessive escaping.103  sourceMap = sourceMap.replace(/\\\\/g, "\\");104  // Trim off the final newline.105  moduleDescriptor.sourceMap = sourceMap;106  return moduleDescriptor.ast.toString();107};...

Full Screen

Full Screen

TransformNode.js

Source:TransformNode.js Github

copy

Full Screen

1import { Vec3, Quat }	from "../Maths.js";2import { Components }	from "../Ecs.js";3class TransformNode{4	constructor(){5		this.level			= 0;			// What level in the Hierachy6		this.parent			= null;			// Entity reference of the parent7		this.parentModified	= false;		// When a parent's Local/World Matrix updates, children are marked to update their world matrix8		this.children		= [];			// List of Children Entities9		this.scale			= new Vec3();	// Accumulated Transform Values, World Space10		this.position		= new Vec3();11		this.rotation		= new Quat();12	}13	////////////////////////////////////////////////////////////////////14	// Child Management15	////////////////////////////////////////////////////////////////////16		static addChild(ep, ec){17			let ph = ep.com.TransformNode;18			if( ph.children.indexOf(ec) != -1){19				console.log("%s is already a child of %s", ec.name, ep.name);20				return Hierarchy;21			}22			//...............................................23			//if child already has a parent, remove itself24			let ch = ec.com.TransformNode;25			if(ch.parent != null) TransformNode.removeChild( ch.parent, ec );26			//...............................................27			ch.parent	= ep;				//Set parent on the child28			ch.level	= ph.level + 1;		//Set the level value for the child29			ph.children.push( ec );			//Add child to parent's children list30			//...............................................31			//if child has its own children, update their level values32			if(ch.children.length > 0) updateChildLevel( ch );33			return TransformNode;34		}35		static removeChild(ep, ec){36			var idx = ep.com.TransformNode.children.indexOf(ec);37			if(idx == -1) console.log("%s is not a child of %s", ec.name, ep.name);38			else{39				//Update Child Data40				ec.com.TransformNode.parent	= null;41				ec.com.TransformNode.level		= 0;42				//Remove from parent43				ep.com.TransformNode.children.splice(idx,1);44			}45			return TransformNode;46		}47	////////////////////////////////////////////////////////////////////48	//49	////////////////////////////////////////////////////////////////////50	static updateNode(e){51		let cn = e.com.TransformNode,52			ct = e.com.Transform;53		if(cn.parent == null){54			cn.position.copy( ct.position );55			cn.rotation.copy( ct.rotation );56			cn.scale.copy( ct.scale );57		}else{58			let pn = cn.parent.com.TransformNode;59			pn.scale.mul( ct.scale, cn.scale );			// parent.scale * child.scale60			pn.rotation.mul( ct.rotation, cn.rotation );	// parent.rotation * child.rotation61			//Calc Position62			// parent.position + ( parent.rotation * ( parent.scale * child.position ) )63			let v = Vec3.mul(pn.scale, ct.position);	// p.scale * c.position;64			Vec3.transformQuat(v, pn.rotation, v).add(pn.position, cn.position);65		}66	}67} Components(TransformNode);68//#######################################################################69//recursive function to update the heirarachy levels in children70function updateChildLevel(h){71	let c, th;72	for(c of h.children){73		th			= c.com.TransformNode;74		th.level	= h.level + 1;75		if(th.children.length > 0) updateChildLevel( th );76	}77}...

Full Screen

Full Screen

all_74.js

Source:all_74.js Github

copy

Full Screen

1var searchData=2[3  ['teapotdata',['teapotData',['../namespacepgr.html#a96f24e8a514f6b90ae9a44781fde3a01',1,'pgr']]],4  ['texturedeleter',['TextureDeleter',['../structpgr_1_1sg_1_1_texture_deleter.html',1,'pgr::sg']]],5  ['textureid',['textureID',['../structpgr_1_1sg_1_1_mesh_geometry_1_1_sub_mesh.html#a85580273e05c8ccca8ccf4ac1b084cea',1,'pgr::sg::MeshGeometry::SubMesh']]],6  ['textureloader',['TextureLoader',['../structpgr_1_1sg_1_1_texture_loader.html',1,'pgr::sg']]],7  ['texturemanager',['TextureManager',['../classpgr_1_1sg_1_1_texture_manager.html',1,'pgr::sg']]],8  ['texturename',['textureName',['../structpgr_1_1sg_1_1_mesh_geometry_1_1_sub_mesh.html#a9624364965ca863e280069b36a498c84',1,'pgr::sg::MeshGeometry::SubMesh']]],9  ['trackball_2eh',['trackball.h',['../trackball_8h.html',1,'']]],10  ['transformnode',['TransformNode',['../classpgr_1_1sg_1_1_transform_node.html',1,'pgr::sg']]],11  ['transformnode',['TransformNode',['../classpgr_1_1sg_1_1_transform_node.html#a5799835b75100e999c4f2b6b009a0585',1,'pgr::sg::TransformNode']]],12  ['transformnode_2eh',['TransformNode.h',['../_transform_node_8h.html',1,'']]],13  ['translate',['translate',['../classpgr_1_1sg_1_1_transform_node.html#a422b0aab9e605c8df43edbe978efd1e8',1,'pgr::sg::TransformNode']]],14  ['triangles',['triangles',['../structpgr_1_1_mesh_data.html#aa85af423c2aee2be54d2f325c21e565b',1,'pgr::MeshData']]]...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1var gherkin = require('cucumber-gherkin');2var fs = require('fs');3var data = fs.readFileSync('test.feature', 'utf8');4var ast = gherkin.parse(data);5var newAst = gherkin.transformNode(ast, function(node) {6    if (node.type === 'Feature') {7        node.name = 'New Name';8    }9    return node;10});11console.log(gherkin.generate(newAst));12Your name to display (optional):13Your name to display (optional):

Full Screen

Using AI Code Generation

copy

Full Screen

1var gherkin = require('gherkin');2var fs = require('fs');3var parser = new gherkin.Parser();4var compiler = new gherkin.Compiler('en');5var featureFile = fs.readFileSync('test.feature', 'utf-8');6var feature = parser.parse(featureFile);7var compiledFeature = compiler.compile(feature);8fs.writeFileSync('test.json', JSON.stringify(compiledFeature));9var fs = require('fs');10var gherkin = require('gherkin');11var json = fs.readFileSync('test.json', 'utf-8');12var feature = JSON.parse(json);13var scenarios = feature.children.filter(function(child) {14  return child.type === 'Scenario';15});16var scenario = scenarios[0];17var scenarioName = scenario.name;18var steps = scenario.steps;19console.log('Scenario: ' + scenarioName);20steps.forEach(function(step) {21  console.log(step.keyword + step.text);22});23var scenarios = feature.children.filter(function(child) {24  return child.type === 'Scenario';25});26var scenarioNames = scenarios.map(function(scenario) {27  return scenario.name;28});

Full Screen

Using AI Code Generation

copy

Full Screen

1var gherkin = require('gherkin');2var parser = new gherkin.Parser();3var transformer = new gherkin.AstTransformer();4';5var gherkinDocument = parser.parse(gherkinSource);6var astNode = transformer.transform(gherkinDocument);7console.log(astNode.feature.name);

Full Screen

Using AI Code Generation

copy

Full Screen

1var gherkin = require('cucumber-gherkin');2var fs = require('fs');3var path = require('path');4var targetFile = path.join(__dirname, 'features', 'test.feature');5var sourceFile = path.join(__dirname, 'features', 'test2.feature');6gherkin.transformNode(sourceFile, targetFile, function(err) {7    if (err) {8        console.log(err);9    } else {10        console.log('File written');11    }12});

Full Screen

Using AI Code Generation

copy

Full Screen

1var gherkin = require('cucumber-gherkin');2var fs = require('fs');3var source = fs.readFileSync('test.feature', 'utf8');4var json = gherkin.transformNode(source);5console.log(json);6{7  "location": {8  },9    {10      "location": {11      },12        {13          "location": {14          },15        },16        {17          "location": {18          },19        }20    }21}

Full Screen

Using AI Code Generation

copy

Full Screen

1var gherkin = require('gherkin');2var parser = new gherkin.Parser();3var transformer = new gherkin.AstBuilder();4";5var gherkinAst = parser.parse(gherkinSource).transformNode(transformer);6var traverseAst = function(astNode, indent) {7  if (astNode == null) {8    return;9  }10  if (astNode.type == 'Feature') {11    console.log(indent + 'Feature: ' + astNode.name);12    astNode.children.forEach(function(node) {13      traverseAst(node, indent + '  ');14    });15  } else if (astNode.type == 'Scenario') {16    console.log(indent + 'Scenario: ' + astNode.name);17    astNode.steps.forEach(function(node) {18      traverseAst(node, indent + '  ');19    });20  } else if (astNode.type == 'Step') {21    console.log(indent + 'Step: ' + astNode.keyword + astNode.name);22  }23}24traverseAst(gherkinAst, '');

Full Screen

Using AI Code Generation

copy

Full Screen

1var gherkin = require('gherkin');2var fs = require('fs');3var gherkinSource = fs.readFileSync('test.feature', 'utf-8');4var gherkinAST = gherkin.Parser().parse(gherkinSource);5var gherkinJSON = gherkin.AstBuilder().build(gherkinAST);6var gherkinSource2 = gherkin.GherkinDocumentBuilder().build(gherkinJSON);7console.log(gherkinSource2);8{9  "scripts": {10  },11  "dependencies": {12  }13}

Full Screen

Cucumber Tutorial:

LambdaTest offers a detailed Cucumber testing tutorial, explaining its features, importance, best practices, and more to help you get started with running your automation testing scripts.

Cucumber Tutorial Chapters:

Here are the detailed Cucumber testing chapters to help you get started:

  • Importance of Cucumber - Learn why Cucumber is important in Selenium automation testing during the development phase to identify bugs and errors.
  • Setting Up Cucumber in Eclipse and IntelliJ - Learn how to set up Cucumber in Eclipse and IntelliJ.
  • Running First Cucumber.js Test Script - After successfully setting up your Cucumber in Eclipse or IntelliJ, this chapter will help you get started with Selenium Cucumber testing in no time.
  • Annotations in Cucumber - To handle multiple feature files and the multiple scenarios in each file, you need to use functionality to execute these scenarios. This chapter will help you learn about a handful of Cucumber annotations ranging from tags, Cucumber hooks, and more to ease the maintenance of the framework.
  • Automation Testing With Cucumber And Nightwatch JS - Learn how to build a robust BDD framework setup for performing Selenium automation testing by integrating Cucumber into the Nightwatch.js framework.
  • Automation Testing With Selenium, Cucumber & TestNG - Learn how to perform Selenium automation testing by integrating Cucumber with the TestNG framework.
  • Integrate Cucumber With Jenkins - By using Cucumber with Jenkins integration, you can schedule test case executions remotely and take advantage of the benefits of Jenkins. Learn how to integrate Cucumber with Jenkins with this detailed chapter.
  • Cucumber Best Practices For Selenium Automation - Take a deep dive into the advanced use cases, such as creating a feature file, separating feature files, and more for Cucumber testing.

Run Cucumber-gherkin automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful