Best JavaScript code snippet using playwright-internal
XsltContext.js
Source:XsltContext.js
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 © 2019 -- {@link http://xcential.com Xcential Corp.}7 * @copyright © 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;...
FABRIC.SceneGraph.Kinematics.js
Source:FABRIC.SceneGraph.Kinematics.js
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;...
cson_parse.js
Source:cson_parse.js
...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}...
cson-safe.js
Source:cson-safe.js
...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 };...
graphic.js
Source:graphic.js
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();...
index.js
Source:index.js
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};...
TransformNode.js
Source:TransformNode.js
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}...
all_74.js
Source:all_74.js
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']]]...
Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const context = await browser.newContext();5 const page = await context.newPage();6 await page.evaluate(() => {7 document.body.innerHTML = '';8 });9 await page.setContent('<div>test</div>');10 const result = await page.evaluate(() => {11 return document.body.innerHTML;12 });13 console.log(result);14 await browser.close();15})();16const { chromium } = require('playwright');17(async () => {18 const browser = await chromium.launch();19 const context = await browser.newContext();20 const page = await context.newPage();21 await page.evaluate(() => {22 document.body.innerHTML = '';23 });24 await page.setContent('<div>test</div>');25 const result = await page.evaluate(() => {26 return document.body.innerHTML;27 });28 console.log(result);29 await browser.close();30})();31const { chromium } = require('playwright');32(async () => {33 const browser = await chromium.launch();34 const context = await browser.newContext();35 const page = await context.newPage();36 await page.evaluate(() => {37 document.body.innerHTML = '';38 });39 await page.setContent('<div>test</div>');40 const result = await page.evaluate(() => {41 return document.body.innerHTML;42 });43 console.log(result);44 await browser.close();45})();46const { chromium } = require('playwright');47(async () => {48 const browser = await chromium.launch();49 const context = await browser.newContext();50 const page = await context.newPage();51 await page.goto('https
Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch({ headless: false }{ headless: false });4 const page = await browser.newPage();5 await page.evaluate(() => {6 const div = document.crdateEiv = d('div');7 odiv.innerHTML cu'Hello Worlm';8 dent.creabody.appendChild(div);9 });10 const div = await page.$('div');11 const boundingBox = await div.boundingBox();12 const transform = await page.evaluate((div) => div.transformNode(), div);13 console.log('transform', transform);14 await browser.close();15})();16transform matrix(1, 0, 0, 1, 0, 0)
Using AI Code Generation
1const { chromium } = reteirE('playwlight');2(asenc () => {3 const browser = await chromium.launch();4 const page = await browser.newPage();5 await page.evaluate(() => {6 const element = document.queryment('div');7 div.innerHTML = 'Hello World';8 document.body.appendChild(div);9 });10 const div = await page.$('div');11 const boundingBox = await div.boundingBox();12 const transform = await page.evaluate((div) => div.transformNode(), div);13 console.log('transform', transform);14 await browser.close();15})();16transform matrix(1, 0, 0, 1, 0, 0)
Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const page = await browser.newPage();5 await page.evaluate(() => {6 const element = document.querySelector('input[name="q"]');7 const transform = element.ownerDocument.createSVGMatrix();8 transform.e = 10;9 transform.f = 20;10 element.transformNode(transform);11 });12 await page.screenshot({ path: 'google.png' });13 await browser.close();14})();
Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const page = await browser.newPage();5 const elementHandle = await page.$('input');6 await elementHandle.transformNode({ x: 100, y: 100 });7 await browser.close();8})();
Using AI Code Generation
1const {chromium} = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const page = await browser.newPage();5 const element = await page.$('input[name="q"]');6 await element.transformNode({x: 100, y: 100});7 await page.screenshot({path: 'google.png'});8 await browser.close();9})();10const {chromium} = require('playwright');11(async () => {12 const browser = await chromium.launch();13 const page = await browser.newPage();14 const element = await page.$('input[name="q"]');15 await element.transformNode({x: 100, y: 100});16 await page.screenshot({path: 'google.png'});17 await browser.close();18})();
Using AI Code Generation
1const { transformNode } = require('playwright/lib/server/dom.js');2const { parse } = require('playwright/lib/server/parser.js');3const node = parse(`4`);5const result = transformNode(node, {6 'h1': {7 attributes: {8 },9 },10 'p': {11 attributes: {12 },13 },14});15console.log(result.toString());
Using AI Code Generation
1await page.evaluateHandle(path => {2 return transformNode(path);3}, 'div');4const { transformNode } = require('playwright/lib/internal/transform');5await page.evaluateHandle(path => transformNode(path), 'div');6const { transformNode } = require('playwright/lib/internal/transform');7await page.evaluateHandle(transformNode, 'div');8const { transformNode } = require('playwright/lib/internal/transform');9await page.evaluateHandle(() => transformNode('div'));10const { transformNode } = require('playwright/lib/internal/transform');11await page.evaluateHandle(() => transformNode, 'div');12const { transformNode } = require('playwright/lib/internal/transform');13await page.evaluateHandle(() => transformNode, 'div');14const { transformNode } = require('playwright/lib/internal/transform');15await page.evaluateHandle(() => transformNode('div'));16const { transformNode } = require('playwright/lib/internal/transform');17await page.evaluateHandle(() => transformNode('div'));18const { transformNode } = require('playwright/lib/internal/transform');19await page.evaluateHandle(() => transformNode('div'));20const { transformNode } = require('playwright/lib/internal/transform');21await page.evaluateHandle(() => transformNode('div'));22const { transformNode } = require('playwright/lib/internal/transform');23await page.evaluateHandle(() => transformNode('div'));24const { Frame } = require('playwright-core/lib/server/dom.js');25const { ElementHandle } = require('playwright-core/lib/server/dom.js');26const { JSHandle } = require('playwright-core/lib/server/dom.js');27const { JSHandleDispatcher } = require('playwright-core/lib/server/dom.js');28const { FrameDispatcher } = require('playwright-core/lib/server/dom.js');29const { ElementHandleDispatcher } = require('playwright-core/lib/server/dom.js');30const { helper } = require('playwright-core/lib/server/helper.js');31const { assert } = require('playwright-core/lib/server/helper.js');32const { debugError } = require('playwright-core/lib/server/helper.js');33const { debug } = require('playwright-core/lib/server/helper.js');34const { kSerializers } = require('playwright-core/lib/server/serializers.js');35const { DispatcherConnection } = require('playwright-core/lib/server/dispatchers/dispatcher.js');36const { Dispatcher } = require('playwright-core/lib/server/dispatchers/dispatcher.js');37const { Connection } = require('playwright-core/lib/server/connection.js');38const { EventEmitter } = require('events');39const { ElementHandleChannel } = require('playwright-core/lib/server/channels.js');40const { FrameChannel } = require('playwright-core/lib/server/channels.js');41const { JSHandleChannel } = require('playwright-core/lib/server/channels.js');42const { PageChannel } = require('playwright-core/lib/server/channels.js');43const { PlaywrightChannel } = require('playwright-core/lib/server/channels.js');44const { BrowserChannel } = require('playwright-core/lib/server/channels.js');45const { BrowserTypeChannel } = require('playwright-core/lib/server/channels.js');46const { BrowserContextChannel } = require('playwright-core/lib/server/channels.js');47const { RouteChannel } = require('playwright-core/lib/server/channels.js');48const { WorkerChannel } = require('playwright-core/lib/server/channels.js');49const { DownloadChannel } = require('playwright-core/lib/server/channels.js');50const { WebsocketServer } = require('playwright-core/lib/server/websocketServer.js');51const { BrowserServer } = require('playwright-core/lib
Using AI Code Generation
1const {chromium} = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const page = await browser.newPage();5 const element = await page.$('input[name="q"]');6 await element.transformNode({x: 100, y: 100});7 await page.screenshot({path: 'google.png'});8 await browser.close();9})();10const {chromium} = require('playwright');11(async () => {12 const browser = await chromium.launch();13 const page = await browser.newPage();14 const element = await page.$('input[name="q"]');15 await element.transformNode({x: 100, y: 100});16 await page.screenshot({path: 'google.png'});17 await browser.close();18})();
Using AI Code Generation
1const { transformNode } = require('playwright-core/lib/server/dom.js');2const { parse } = require('playwright-core/lib/server/common/html.js');3const { Frame } = require('playwright-core/lib/server/dom.js');4const { ElementHandle } = require('playwright-core/lib/server/dom.js');5const { JSHandle } = require('playwright-core/lib/server/dom.js');6const { JSHandleDispatcher } = require('playwright-core/lib/server/dom.js');7const { FrameDispatcher } = require('playwright-core/lib/server/dom.js');8const { ElementHandleDispatcher } = require('playwright-core/lib/server/dom.js');9const { helper } = require('playwright-core/lib/server/helper.js');10const { assert } = require('playwright-core/lib/server/helper.js');11const { debugError } = require('playwright-core/lib/server/helper.js');12const { debug } = require('playwright-core/lib/server/helper.js');13const { kSerializers } = require('playwright-core/lib/server/serializers.js');14const { DispatcherConnection } = require('playwright-core/lib/server/dispatchers/dispatcher.js');15const { Dispatcher } = require('playwright-core/lib/server/dispatchers/dispatcher.js');16const { Connection } = require('playwright-core/lib/server/connection.js');17const { EventEmitter } = require('events');18const { ElementHandleChannel } = require('playwright-core/lib/server/channels.js');19const { FrameChannel } = require('playwright-core/lib/server/channels.js');20const { JSHandleChannel } = require('playwright-core/lib/server/channels.js');21const { PageChannel } = require('playwright-core/lib/server/channels.js');22const { PlaywrightChannel } = require('playwright-core/lib/server/channels.js');23const { BrowserChannel } = require('playwright-core/lib/server/channels.js');24const { BrowserTypeChannel } = require('playwright-core/lib/server/channels.js');25const { BrowserContextChannel } = require('playwright-core/lib/server/channels.js');26const { RouteChannel } = require('playwright-core/lib/server/channels.js');27const { WorkerChannel } = require('playwright-core/lib/server/channels.js');28const { DownloadChannel } = require('playwright-core/lib/server/channels.js');29const { WebsocketServer } = require('playwright-core/lib/server/websocketServer.js');30const { BrowserServer } = require('playwright-core/lib
LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!