compiler.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. const Promise = require('bluebird');
  2. const merge = require('merge-options');
  3. const FileRequest = require('./request');
  4. const RuleSet = require('./rules');
  5. const Sprite = require('./sprite');
  6. const SpriteSymbol = require('./symbol');
  7. const symbolFactory = require('./symbol-factory');
  8. const spriteFactory = require('./sprite-factory');
  9. const defaultConfig = {
  10. rules: [
  11. { test: /\.svg$/, value: 'sprite.svg' }
  12. ],
  13. symbolFactory,
  14. spriteFactory
  15. };
  16. class Compiler {
  17. static sortSymbols(symbols) {
  18. symbols.sort((leftSymbol, rightSymbol) => {
  19. const leftId = leftSymbol.id;
  20. const rightId = rightSymbol.id;
  21. if (leftId === rightId) {
  22. return 0;
  23. }
  24. return leftId < rightId ? -1 : 1;
  25. });
  26. return symbols;
  27. }
  28. constructor(cfg = {}) {
  29. const config = this.config = merge(defaultConfig, cfg);
  30. this.rules = new RuleSet(config.rules);
  31. this.symbols = [];
  32. }
  33. /**
  34. * @param {string} content
  35. * @param {string} path
  36. * @param {string} [id]
  37. * @return {Promise<SpriteSymbol>}
  38. */
  39. addSymbol({ path, content, id }) {
  40. const symbols = this.symbols;
  41. const factory = this.config.symbolFactory;
  42. const request = new FileRequest(path);
  43. const options = { id, request, content, factory };
  44. return SpriteSymbol.create(options).then((newSymbol) => {
  45. const existing = symbols.find(s => s.request.equals(request));
  46. if (!existing) {
  47. symbols.push(newSymbol);
  48. Compiler.sortSymbols(symbols);
  49. return newSymbol;
  50. }
  51. const existingIndex = existing ? symbols.indexOf(existing) : -1;
  52. const allExceptCurrent = symbols
  53. .filter(s => s.request.fileEquals(request) && !s.request.queryEquals(request))
  54. .map(symbol => ({ symbol, index: symbols.indexOf(symbol) }));
  55. symbols[existingIndex] = newSymbol;
  56. Compiler.sortSymbols(symbols);
  57. return Promise.map(allExceptCurrent, ({ symbol, index }) => {
  58. const opts = { id: symbol.id, request: symbol.request, content, factory };
  59. return SpriteSymbol.create(opts).then(created => symbols[index] = created);
  60. }).then(() => newSymbol);
  61. });
  62. }
  63. /**
  64. * @return {Promise<Array<Sprite>>}
  65. */
  66. compile() {
  67. const symbols = this.symbols;
  68. const rules = this.rules.rules;
  69. const factory = this.config.spriteFactory;
  70. return Promise.map(rules, (rule) => {
  71. const spriteSymbols = [];
  72. const filename = rule.uri;
  73. symbols.forEach((symbol) => {
  74. const isMatch = rule.match(symbol.request.file);
  75. if (isMatch) {
  76. spriteSymbols.push(symbol);
  77. }
  78. });
  79. return spriteSymbols.length > 0 ?
  80. Sprite.create({ symbols: spriteSymbols, filename, factory }) :
  81. null;
  82. }).filter(result => result !== null);
  83. }
  84. }
  85. module.exports = Compiler;
  86. module.exports.defaultConfig = defaultConfig;