style-xform.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. const BaseXform = require('../base-xform');
  2. const AlignmentXform = require('./alignment-xform');
  3. const ProtectionXform = require('./protection-xform');
  4. // <xf numFmtId="[numFmtId]" fontId="[fontId]" fillId="[fillId]" borderId="[xf.borderId]" xfId="[xfId]">
  5. // Optional <alignment>
  6. // Optional <protection>
  7. // </xf>
  8. // Style assists translation from style model to/from xlsx
  9. class StyleXform extends BaseXform {
  10. constructor(options) {
  11. super();
  12. this.xfId = !!(options && options.xfId);
  13. this.map = {
  14. alignment: new AlignmentXform(),
  15. protection: new ProtectionXform(),
  16. };
  17. }
  18. get tag() {
  19. return 'xf';
  20. }
  21. render(xmlStream, model) {
  22. xmlStream.openNode('xf', {
  23. numFmtId: model.numFmtId || 0,
  24. fontId: model.fontId || 0,
  25. fillId: model.fillId || 0,
  26. borderId: model.borderId || 0,
  27. });
  28. if (this.xfId) {
  29. xmlStream.addAttribute('xfId', model.xfId || 0);
  30. }
  31. if (model.numFmtId) {
  32. xmlStream.addAttribute('applyNumberFormat', '1');
  33. }
  34. if (model.fontId) {
  35. xmlStream.addAttribute('applyFont', '1');
  36. }
  37. if (model.fillId) {
  38. xmlStream.addAttribute('applyFill', '1');
  39. }
  40. if (model.borderId) {
  41. xmlStream.addAttribute('applyBorder', '1');
  42. }
  43. if (model.alignment) {
  44. xmlStream.addAttribute('applyAlignment', '1');
  45. }
  46. if (model.protection) {
  47. xmlStream.addAttribute('applyProtection', '1');
  48. }
  49. /**
  50. * Rendering tags causes close of XML stream.
  51. * Therefore adding attributes must be done before rendering tags.
  52. */
  53. if (model.alignment) {
  54. this.map.alignment.render(xmlStream, model.alignment);
  55. }
  56. if (model.protection) {
  57. this.map.protection.render(xmlStream, model.protection);
  58. }
  59. xmlStream.closeNode();
  60. }
  61. parseOpen(node) {
  62. if (this.parser) {
  63. this.parser.parseOpen(node);
  64. return true;
  65. }
  66. // used during sax parsing of xml to build font object
  67. switch (node.name) {
  68. case 'xf':
  69. this.model = {
  70. numFmtId: parseInt(node.attributes.numFmtId, 10),
  71. fontId: parseInt(node.attributes.fontId, 10),
  72. fillId: parseInt(node.attributes.fillId, 10),
  73. borderId: parseInt(node.attributes.borderId, 10),
  74. };
  75. if (this.xfId) {
  76. this.model.xfId = parseInt(node.attributes.xfId, 10);
  77. }
  78. return true;
  79. case 'alignment':
  80. this.parser = this.map.alignment;
  81. this.parser.parseOpen(node);
  82. return true;
  83. case 'protection':
  84. this.parser = this.map.protection;
  85. this.parser.parseOpen(node);
  86. return true;
  87. default:
  88. return false;
  89. }
  90. }
  91. parseText(text) {
  92. if (this.parser) {
  93. this.parser.parseText(text);
  94. }
  95. }
  96. parseClose(name) {
  97. if (this.parser) {
  98. if (!this.parser.parseClose(name)) {
  99. if (this.map.protection === this.parser) {
  100. this.model.protection = this.parser.model;
  101. } else {
  102. this.model.alignment = this.parser.model;
  103. }
  104. this.parser = undefined;
  105. }
  106. return true;
  107. }
  108. return name !== 'xf';
  109. }
  110. }
  111. module.exports = StyleXform;