base-xform.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. "use strict";
  2. const parseSax = require('../../utils/parse-sax');
  3. const XmlStream = require('../../utils/xml-stream');
  4. /* 'virtual' methods used as a form of documentation */
  5. /* eslint-disable class-methods-use-this */
  6. // Base class for Xforms
  7. class BaseXform {
  8. // constructor(/* model, name */) {}
  9. // ============================================================
  10. // Virtual Interface
  11. prepare( /* model, options */
  12. ) {
  13. // optional preparation (mutation) of model so it is ready for write
  14. }
  15. render( /* xmlStream, model */
  16. ) {
  17. // convert model to xml
  18. }
  19. parseOpen(node) {
  20. // XML node opened
  21. }
  22. parseText(text) {
  23. // chunk of text encountered for current node
  24. }
  25. parseClose(name) {
  26. // XML node closed
  27. }
  28. reconcile(model, options) {
  29. // optional post-parse step (opposite to prepare)
  30. }
  31. // ============================================================
  32. reset() {
  33. // to make sure parses don't bleed to next iteration
  34. this.model = null;
  35. // if we have a map - reset them too
  36. if (this.map) {
  37. Object.values(this.map).forEach(xform => {
  38. if (xform instanceof BaseXform) {
  39. xform.reset();
  40. } else if (xform.xform) {
  41. xform.xform.reset();
  42. }
  43. });
  44. }
  45. }
  46. mergeModel(obj) {
  47. // set obj's props to this.model
  48. this.model = Object.assign(this.model || {}, obj);
  49. }
  50. async parse(saxParser) {
  51. for await (const events of saxParser) {
  52. for (const {
  53. eventType,
  54. value
  55. } of events) {
  56. if (eventType === 'opentag') {
  57. this.parseOpen(value);
  58. } else if (eventType === 'text') {
  59. this.parseText(value);
  60. } else if (eventType === 'closetag') {
  61. if (!this.parseClose(value.name)) {
  62. return this.model;
  63. }
  64. }
  65. }
  66. }
  67. return this.model;
  68. }
  69. async parseStream(stream) {
  70. return this.parse(parseSax(stream));
  71. }
  72. get xml() {
  73. // convenience function to get the xml of this.model
  74. // useful for manager types that are built during the prepare phase
  75. return this.toXml(this.model);
  76. }
  77. toXml(model) {
  78. const xmlStream = new XmlStream();
  79. this.render(xmlStream, model);
  80. return xmlStream.xml;
  81. }
  82. // ============================================================
  83. // Useful Utilities
  84. static toAttribute(value, dflt) {
  85. let always = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  86. if (value === undefined) {
  87. if (always) {
  88. return dflt;
  89. }
  90. } else if (always || value !== dflt) {
  91. return value.toString();
  92. }
  93. return undefined;
  94. }
  95. static toStringAttribute(value, dflt) {
  96. let always = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  97. return BaseXform.toAttribute(value, dflt, always);
  98. }
  99. static toStringValue(attr, dflt) {
  100. return attr === undefined ? dflt : attr;
  101. }
  102. static toBoolAttribute(value, dflt) {
  103. let always = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  104. if (value === undefined) {
  105. if (always) {
  106. return dflt;
  107. }
  108. } else if (always || value !== dflt) {
  109. return value ? '1' : '0';
  110. }
  111. return undefined;
  112. }
  113. static toBoolValue(attr, dflt) {
  114. return attr === undefined ? dflt : attr === '1';
  115. }
  116. static toIntAttribute(value, dflt) {
  117. let always = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  118. return BaseXform.toAttribute(value, dflt, always);
  119. }
  120. static toIntValue(attr, dflt) {
  121. return attr === undefined ? dflt : parseInt(attr, 10);
  122. }
  123. static toFloatAttribute(value, dflt) {
  124. let always = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  125. return BaseXform.toAttribute(value, dflt, always);
  126. }
  127. static toFloatValue(attr, dflt) {
  128. return attr === undefined ? dflt : parseFloat(attr);
  129. }
  130. }
  131. module.exports = BaseXform;
  132. //# sourceMappingURL=base-xform.js.map