plugins.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. var Immutable = require("immutable");
  2. var Map = Immutable.Map;
  3. var isMap = Immutable.Map.isMap;
  4. var List = Immutable.List;
  5. var qs = require("qs");
  6. var path = require("path");
  7. var fs = require("fs");
  8. var Plugin = Immutable.Record({
  9. moduleName: "",
  10. name: "",
  11. active: true,
  12. module: undefined,
  13. options: Map({}),
  14. via: "inline",
  15. dir: process.cwd(),
  16. init: undefined,
  17. errors: List([])
  18. });
  19. /**
  20. * Accept a string/object
  21. * and resolve it into the plugin format above
  22. * @param item
  23. * @returns {*}
  24. */
  25. function resolvePlugin(item) {
  26. /**
  27. * Handle when string was given, such as plugins: ['bs-html-injector']
  28. */
  29. if (typeof item === "string") {
  30. return getFromString(item);
  31. }
  32. if (!isMap(item)) {
  33. return new Plugin().mergeDeep({
  34. errors: [new Error("Plugin not supported in this format")]
  35. });
  36. }
  37. if (item.has("module")) {
  38. var nameOrObj = item.get("module");
  39. var options = item.get("options");
  40. /**
  41. * The 'module' key can be a string, this allows
  42. * inline plugin references, but with options
  43. * eg:
  44. *
  45. * bs.init({
  46. * plugins: [
  47. * {
  48. * module: './myjs-file.js'
  49. * options: {
  50. * files: "*.html"
  51. * }
  52. * }
  53. * ]
  54. * });
  55. */
  56. if (typeof nameOrObj === "string") {
  57. return getFromString(nameOrObj).mergeDeep({
  58. options: options
  59. });
  60. }
  61. /**
  62. * If the plugin was given completely inline (because it needs options)
  63. * eg:
  64. *
  65. * bs.init({
  66. * plugins: [
  67. * {
  68. * module: {
  69. * plugin: function() {
  70. * console.log('My plugin code')
  71. * }
  72. * },
  73. * options: {
  74. * files: "*.html"
  75. * }
  76. * }
  77. * ]
  78. * })
  79. */
  80. if (Immutable.Map.isMap(nameOrObj)) {
  81. return new Plugin({
  82. module: nameOrObj,
  83. options: options
  84. });
  85. }
  86. }
  87. /**
  88. * If a module was given directly. For example, ater calling require.
  89. *
  90. * eg:
  91. * var myplugin = require('./some-js');
  92. * bs.init({plugins: [myplugin]});
  93. */
  94. if (item.has("plugin")) {
  95. return new Plugin({
  96. module: item
  97. });
  98. }
  99. /**
  100. * If we reach here, the plugin option was used incorrectly
  101. */
  102. return new Plugin().mergeDeep({
  103. errors: [new Error("Plugin was not configured correctly")]
  104. });
  105. }
  106. module.exports.resolvePlugin = resolvePlugin;
  107. /**
  108. * Load a plugin from disk
  109. * @param item
  110. * @returns {*}
  111. */
  112. function requirePlugin(item) {
  113. /**
  114. * if the "module" property already exists and
  115. * is not a string, then we bail and don't bother looking
  116. * for the file
  117. */
  118. if (item.get("module") && typeof item.get("module") !== "string") {
  119. return item;
  120. }
  121. try {
  122. /**
  123. * Try a raw node require() call - this will be how
  124. * regular "npm installed" plugins wil work
  125. */
  126. var maybe = require.resolve(item.get("name"));
  127. return item.set("module", require(maybe));
  128. }
  129. catch (e) {
  130. /**
  131. * If require threw an MODULE_NOT_FOUND error, try again
  132. * by resolving from cwd. This is needed since cli
  133. * users will not add ./ to the front of a path (which
  134. * node requires to resolve from cwd)
  135. */
  136. if (e.code === "MODULE_NOT_FOUND") {
  137. var maybe = path.resolve(process.cwd(), item.get("name"));
  138. if (fs.existsSync(maybe)) {
  139. return item.set("module", require(maybe));
  140. }
  141. else {
  142. /**
  143. * Finally return a plugin that contains the error
  144. * this will be picked up later and discarded
  145. */
  146. return item.update("errors", function (errors) {
  147. return errors.concat(e);
  148. });
  149. }
  150. }
  151. throw e;
  152. }
  153. }
  154. module.exports.requirePlugin = requirePlugin;
  155. function getFromString(string) {
  156. /**
  157. * We allow query strings for plugins, so always split on ?
  158. */
  159. var split = string.split("?");
  160. var outGoing = new Plugin({
  161. moduleName: split[0],
  162. name: split[0]
  163. });
  164. if (split.length > 1) {
  165. return outGoing.update("options", function (opts) {
  166. return opts.mergeDeep(qs.parse(split[1]));
  167. });
  168. }
  169. return outGoing;
  170. }
  171. //# sourceMappingURL=plugins.js.map