source-map-url.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. // Copyright 2014 Simon Lydell
  2. // X11 (“MIT”) Licensed. (See LICENSE.)
  3. var expect = require("expect.js")
  4. var sourceMappingURL = require("../")
  5. var comments = {
  6. universal: [
  7. "/*# sourceMappingURL=foo.js.map */"
  8. ],
  9. js: [
  10. "//# sourceMappingURL=foo.js.map"
  11. ],
  12. block: [
  13. "/*",
  14. "# sourceMappingURL=foo.js.map",
  15. "*/"
  16. ],
  17. mix: [
  18. "/*",
  19. "//# sourceMappingURL=foo.js.map",
  20. "*/"
  21. ]
  22. }
  23. var nonTrailingComments = {
  24. jsLeading: {
  25. contents: [
  26. "//# sourceMappingURL=foo.js.map",
  27. "(function(){})"
  28. ],
  29. solution: [
  30. "(function(){})"
  31. ]
  32. },
  33. mixEmbedded: {
  34. contents: [
  35. "/*! Library Name v1.0.0",
  36. "//# sourceMappingURL=foo.js.map",
  37. "*/",
  38. "(function(){})"
  39. ],
  40. solution: [
  41. "/*! Library Name v1.0.0",
  42. "*/",
  43. "(function(){})"
  44. ]
  45. }
  46. }
  47. function forEachComment(fn) {
  48. forOf(comments, function(name, comment) {
  49. var description = "the '" + name + "' syntax with "
  50. fn(comment.join("\n"), description + "regular newlines")
  51. fn(comment.join("\r\n"), description + "Windows newlines")
  52. })
  53. }
  54. function forEachNonTrailingComment(fn) {
  55. forOf(nonTrailingComments, function(name, comment) {
  56. var description = "the '" + name + "' syntax with "
  57. fn({
  58. contents: comment.contents.join("\n"),
  59. solution: comment.solution.join("\n")
  60. }, description + "regular newlines")
  61. fn({
  62. contents: comment.contents.join("\r\n"),
  63. solution: comment.solution.join("\r\n")
  64. }, description + "Windows newlines")
  65. })
  66. }
  67. function forOf(obj, fn) {
  68. for (var key in obj) {
  69. if (Object.prototype.hasOwnProperty.call(obj, key)) {
  70. fn(key, obj[key])
  71. }
  72. }
  73. }
  74. describe("sourceMappingURL", function() {
  75. describe(".getFrom", function() {
  76. forEachComment(function(comment, description) {
  77. it("gets the url from " + description, function() {
  78. expect(sourceMappingURL.getFrom("code\n" + comment))
  79. .to.equal("foo.js.map")
  80. expect(sourceMappingURL.getFrom("code" + comment))
  81. .to.equal("foo.js.map")
  82. expect(sourceMappingURL.getFrom(comment))
  83. .to.equal("foo.js.map")
  84. })
  85. })
  86. forEachNonTrailingComment(function(comment, description) {
  87. it("gets the url from " + description, function() {
  88. expect(sourceMappingURL.getFrom("code\n" + comment.contents))
  89. .to.equal("foo.js.map")
  90. expect(sourceMappingURL.getFrom("code" + comment.contents))
  91. .to.equal("foo.js.map")
  92. expect(sourceMappingURL.getFrom(comment.contents))
  93. .to.equal("foo.js.map")
  94. })
  95. })
  96. it("returns null if no comment", function() {
  97. expect(sourceMappingURL.getFrom("code"))
  98. .to.equal(null)
  99. })
  100. it("can return an empty string as url", function() {
  101. expect(sourceMappingURL.getFrom("/*# sourceMappingURL= */"))
  102. .to.equal("")
  103. })
  104. it("is detachable", function() {
  105. var get = sourceMappingURL.getFrom
  106. expect(get("/*# sourceMappingURL=foo */"))
  107. .to.equal("foo")
  108. })
  109. })
  110. describe(".existsIn", function() {
  111. forEachComment(function(comment, description) {
  112. it("returns true for " + description, function() {
  113. expect(sourceMappingURL.existsIn("code\n" + comment))
  114. .to.equal(true)
  115. expect(sourceMappingURL.existsIn("code" + comment))
  116. .to.equal(true)
  117. expect(sourceMappingURL.existsIn(comment))
  118. .to.equal(true)
  119. })
  120. })
  121. forEachNonTrailingComment(function(comment, description) {
  122. it("returns true for " + description, function() {
  123. expect(sourceMappingURL.existsIn("code\n" + comment.contents))
  124. .to.equal(true)
  125. expect(sourceMappingURL.existsIn("code" + comment.contents))
  126. .to.equal(true)
  127. expect(sourceMappingURL.existsIn(comment.contents))
  128. .to.equal(true)
  129. })
  130. })
  131. it("returns false if no comment", function() {
  132. expect(sourceMappingURL.existsIn("code"))
  133. .to.equal(false)
  134. })
  135. it("is detachable", function() {
  136. var has = sourceMappingURL.existsIn
  137. expect(has("/*# sourceMappingURL=foo */"))
  138. .to.equal(true)
  139. })
  140. })
  141. describe(".removeFrom", function() {
  142. forEachComment(function(comment, description) {
  143. it("removes the comment for " + description, function() {
  144. expect(sourceMappingURL.removeFrom("code\n" + comment))
  145. .to.equal("code\n")
  146. expect(sourceMappingURL.removeFrom("code" + comment))
  147. .to.equal("code")
  148. expect(sourceMappingURL.removeFrom(comment))
  149. .to.equal("")
  150. })
  151. })
  152. forEachNonTrailingComment(function(comment, description) {
  153. it("removes the comment for " + description, function() {
  154. expect(sourceMappingURL.removeFrom("code\n" + comment.contents))
  155. .to.equal("code\n" + comment.solution)
  156. expect(sourceMappingURL.removeFrom("code" + comment.contents))
  157. .to.equal("code" + comment.solution)
  158. expect(sourceMappingURL.removeFrom(comment.contents))
  159. .to.equal(comment.solution)
  160. })
  161. })
  162. it("does nothing if no comment", function() {
  163. expect(sourceMappingURL.removeFrom("code\n"))
  164. .to.equal("code\n")
  165. })
  166. it("is detachable", function() {
  167. var remove = sourceMappingURL.removeFrom
  168. expect(remove("/*# sourceMappingURL=foo */"))
  169. .to.equal("")
  170. })
  171. })
  172. describe(".insertBefore", function() {
  173. forEachComment(function(comment, description) {
  174. it("inserts a string before the comment for " + description, function() {
  175. expect(sourceMappingURL.insertBefore("code\n" + comment, "more code\n"))
  176. .to.equal("code\nmore code\n" + comment)
  177. expect(sourceMappingURL.insertBefore("code" + comment, "\nmore code"))
  178. .to.equal("code\nmore code" + comment)
  179. expect(sourceMappingURL.insertBefore(comment, "some code"))
  180. .to.equal("some code" + comment)
  181. })
  182. })
  183. it("inserts a string before an embedded comment", function() {
  184. expect(sourceMappingURL.insertBefore("/*! Library Name v1.0.0\n" +
  185. "//# sourceMappingURL=foo.js.map\n*/\n(function(){})", "code\n"))
  186. .to.equal("/*! Library Name v1.0.0\ncode\n" +
  187. "//# sourceMappingURL=foo.js.map\n*/\n(function(){})")
  188. })
  189. it("inserts a string before a leading comment", function() {
  190. expect(sourceMappingURL.insertBefore("//# sourceMappingURL=foo.js.map\n" +
  191. "(function(){})", "code\n"))
  192. .to.equal("code\n//# sourceMappingURL=foo.js.map\n" +
  193. "(function(){})")
  194. })
  195. it("appends if no comment", function() {
  196. expect(sourceMappingURL.insertBefore("code", "\nmore code"))
  197. .to.equal("code\nmore code")
  198. })
  199. it("is detachable", function() {
  200. var insertBefore = sourceMappingURL.insertBefore
  201. expect(insertBefore("/*# sourceMappingURL=foo */", "bar"))
  202. .to.equal("bar/*# sourceMappingURL=foo */")
  203. })
  204. })
  205. describe(".regex", function() {
  206. it("includes ._innerRegex", function() {
  207. expect(sourceMappingURL.regex.source)
  208. .to.contain(sourceMappingURL._innerRegex.source)
  209. })
  210. var match = function(code) {
  211. expect(code)
  212. .to.match(sourceMappingURL.regex)
  213. }
  214. var noMatch = function(code) {
  215. expect(code)
  216. .not.to.match(sourceMappingURL.regex)
  217. }
  218. forEachComment(function(comment, description) {
  219. it("matches " + description, function() {
  220. match("code\n" + comment)
  221. match("code" + comment)
  222. match(comment)
  223. })
  224. it("matches " + description + ", with trailing whitespace", function() {
  225. match(comment + " ")
  226. match(comment + "\n")
  227. match(comment + "\n\n\t\n \t ")
  228. })
  229. })
  230. it("does not match some cases that are easy to mess up", function() {
  231. noMatch(
  232. "/* # sourceMappingURL=foo */"
  233. )
  234. noMatch(
  235. "// # sourceMappingURL=foo"
  236. )
  237. })
  238. it("is liberal regarding inner whitespace", function() {
  239. match(
  240. "/*# sourceMappingURL=foo*/"
  241. )
  242. match(
  243. "/*# sourceMappingURL=foo */"
  244. )
  245. match(
  246. "/*# sourceMappingURL=foo \t\n" +
  247. "*/"
  248. )
  249. match(
  250. "/* \n" +
  251. "# sourceMappingURL=foo\n" +
  252. "*/"
  253. )
  254. match(
  255. "/*\n" +
  256. "# sourceMappingURL=foo\n" +
  257. " */"
  258. )
  259. match(
  260. "/*\n" +
  261. "# sourceMappingURL=foo\n" +
  262. "\n" +
  263. "\t\n" +
  264. "*/"
  265. )
  266. })
  267. })
  268. describe("._innerRegex", function() {
  269. it("matches the contents of sourceMappingURL comments", function() {
  270. expect("# sourceMappingURL=http://www.example.com/foo/bar.js.map")
  271. .to.match(sourceMappingURL._innerRegex)
  272. })
  273. it("captures the url in the first capture group", function() {
  274. expect(sourceMappingURL._innerRegex.exec("# sourceMappingURL=foo")[1])
  275. .to.equal("foo")
  276. })
  277. it("supports the legacy syntax", function() {
  278. expect("@ sourceMappingURL=http://www.example.com/foo/bar.js.map")
  279. .to.match(sourceMappingURL._innerRegex)
  280. })
  281. })
  282. })