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